I have tried Android SDK above 5.1 OS. I want to send sms using SIM selection option. I tried this Program. It's taking sim1 only. It does not take second sim.
My Program
public class MainActivity extends AppCompatActivity {
Context mContext = MainActivity.this ;
String SENT = "SMS_SENT";
String DELIVERED = "SMS_DELIVERED";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sendSMS("XXXXXXXX77","Sent by Dual Sim Support Testing");
}
public void sendSMS(final String paramString1,final String paramString2)
{
final PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.SENT), 0);
final PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.DELIVERED), 0);
Log.v("ppi", "DUal SIm:Build.VERSION.SDK_INT:" + Build.VERSION.SDK_INT);
if (Build.VERSION.SDK_INT >= 22)
{
SubscriptionManager localSubscriptionManager = SubscriptionManager.from(mContext);
if (localSubscriptionManager.getActiveSubscriptionInfoCount() > 1)
{
List localList = localSubscriptionManager.getActiveSubscriptionInfoList();
final String[] arrayOfString = new String[localList.size()];
int i = 0;
Iterator localIterator = localList.iterator();
while (localIterator.hasNext())
{
SubscriptionInfo localSubscriptionInfo = (SubscriptionInfo)localIterator.next();
localSubscriptionInfo.getSubscriptionId();
//log.d("22 api level ", "got dual sim: ");
int j = i + 1;
arrayOfString[i] = (localSubscriptionInfo.getCarrierName().toString() + " " + localSubscriptionInfo.getNumber());
i = j;
}
Log.v("ppi","DUal SIm:arrayOfString:"+arrayOfString.length);
for(i = 0; i < arrayOfString.length; i++ ){
Log.v("ppi","DUal SIm:arrayOfString:"+arrayOfString[i]);
}
final AlertDialog.Builder localBuilder = new AlertDialog.Builder(mContext);
localBuilder.setTitle("Choose SIM ");
localBuilder
.setCancelable(false)
.setPositiveButton("SIM1",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
SmsManager.getDefault().sendTextMessage(paramString1, null, paramString2, localPendingIntent1, localPendingIntent2);
//dialog.cancel();
}
})
.setNegativeButton("SIM2", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// if this button is clicked, just close
// the dialog box and do nothing
SmsManager.getDefault().sendTextMessage(paramString1, null, paramString2, localPendingIntent1, localPendingIntent2);
// dialog.cancel();
}
});
localBuilder.setCancelable(false);
localBuilder.show();
}
}
SmsManager.getDefault().sendTextMessage(paramString1, null, paramString2, localPendingIntent1, localPendingIntent2);
}
}
Finally, I found exact Sim Selection Option for above android os version 5.1 and above.
public void sendDualSimSMSOption(final String ToaddrmobileNo, final String message) {
// detect os is below 22 or not
if (Build.VERSION.SDK_INT >= 22) {
final PendingIntent PendingIntent1 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.SENT), 0);
final PendingIntent PendingIntent2 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.DELIVERED), 0);
SubscriptionManager localSubscripManager = SubscriptionManager.from(mContext);
ArrayList<Integer> saveSubscripID = new ArrayList<Integer>();
ArrayList<String> saveSimOperatorNames = new ArrayList<String>();
ArrayList<String> saveSimSerialNumbers = new ArrayList<String>();
final int[] subscripInformationArray = new int[2];
if (localSubscripManager.getActiveSubscriptionInfoCount() > 1) {
List localList = localSubscripManager.getActivesubscripInformationList();
final String[] arrayOfStringData = new String[localList.size()];
int i = 0;
Iterator localIterator = localList.iterator();
while (localIterator.hasNext()) {
SubscriptionInfo localSubscriptionInfo = (SubscriptionInfo) localIterator.next();
localSubscriptionInfo.getSubscriptionId();
Log.v("SIM", "22 api level..got dual sim: ");
int j = i + 1;
String SimCarrierName = (localSubscriptionInfo.getCarrierName().toString().trim());
String SimDisplayName = (localSubscriptionInfo.getDisplayName().toString().trim());
String SimSerialNo = (localSubscriptionInfo.getIccId().toString().trim());
if( SimCarrierName != null && SimCarrierName.length() > 0)
{
arrayOfStringData[i] = SimCarrierName ;
Log.v('SIM', "SIM.getCarrierName:", arrayOfStringData[i]);
}
else {
arrayOfStringData[i] = SimDisplayName ;
Log.v('SIM', "SIM.SimDisplayName:", arrayOfStringData[i]);
}
i = j;
}
SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext());
List<SubscriptionInfo> subscripInformationList = subscriptionManager.getActivesubscripInformationList();
for (SubscriptionInfo subscriptionInfo : subscripInformationList) {
int subscriptionId = subscriptionInfo.getSubscriptionId();
Log.v('SIM', "SIM.subscriptionId:",""+subscriptionId);
}
for (i = 0; i < subscripInformationList.size(); i++) {
Log.v("SIM", "DUal SIm:subscripInformationList:" + subscripInformationList.get(i));
Log.v("SIM", "DUal SIm:getSubscriptionId:" + subscripInformationList.get(i).getSubscriptionId());
subscripInformationArray[i] = subscripInformationList.get(i).getSubscriptionId();
saveSubscripID.add(subscripInformationList.get(i).getSubscriptionId());
saveSimSerialNumbers.add(subscripInformationList.get(i).getIccId());
}
for (i = 0; i < arrayOfStringData.length; i++) {
Log.v("SIM", "DUal SIm:arrayOfStringData:" + arrayOfStringData[i]);
Log.v("SIM", "DUal SIm:subscripInformationArray:"+ subscripInformationArray[i]);
if( arrayOfStringData[i] != null && arrayOfStringData[i].length() > 0)
{
saveSimOperatorNames.add(arrayOfStringData[i]);
}
else{
saveSimOperatorNames.add("Sim "+(i+1));
}
}
// this is the method to show sim selection dialog with above sim serials info.
SimSelection_ShowDialogBox(context, ToAddrMobNo, message,saveSubscripId, saveSimOperaNames,saveSimSerialNumbers);
}
}
else{
// else part. default sim taking to send sms
}
}
That is because you have:
SmsManager.getDefault()
which is SIM1, instead of having:
SmsManager.getSmsManagerForSubscriptionId(int subscriptionId)
when sending SMS in your dialog buttons click events.
I looked into SubscriptionManager class and found a method to get subsCription info for perticular sim slot
This worked for me:
public void sendSMS(final String number,final String text)
{
final PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.SENT), 0);
final PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(mContext, 0, new Intent(this.DELIVERED), 0);
if (Build.VERSION.SDK_INT >= 22)
{
SubscriptionManager subscriptionManager=((Activity)mContext).getSystemService(SubscriptionManager.class);
SubscriptionInfo subscriptionInfo=subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(simIndex);
SmsManager.getSmsManagerForSubscriptionId(subscriptionInfo.getSubscriptionId()).sendTextMessage(number, null, text, localPendingIntent1, localPendingIntent2);
}
SmsManager.getSmsManagerForSubscriptionId(subscriptionInfo.getSubscriptionId()).sendTextMessage(number, null, text, localPendingIntent1, localPendingIntent2);
}
Where simIndex is 0 for sim1 and 1 for sim2
Related
I have set OnClickListener, on drawableRight in edittext for phone numbers so, can you help to open Call Log when I press the button, my phone's call log box opens and I select one of the recently used numbers for the edittext box. so, now What to write for the action for onclicklistener?
I have written code in MainActivity.java as:
public class MainActivity extends AppCompatActivity {
CountryCodePicker ccp;
TextInputEditText number;
#SuppressLint({"ResourceType", "ClickableViewAccessibility"})
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ccp = findViewById(R.id.ccp);
number = (TextInputEditText) findViewById(R.id.Phone_Number);
number.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
final int DRAWABLE_LEFT = 0;
final int DRAWABLE_TOP = 1;
final int DRAWABLE_RIGHT = 2;
final int DRAWABLE_BOTTOM = 3;
if(event.getAction() == MotionEvent.ACTION_UP) {
if(event.getRawX() >= (number.getRight() - number.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) {
// your action here
CallsProvider callsProvider = new CallsProvider (getApplicationContext());
callsProvider.getCalls();
}
}
return false;
}
});
}
}
You have to get the permissions as below
<uses-permission android:name="android.permission.READ_CALL_LOG"></uses-permission>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"></uses-permission>
Use this code to get call logs
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[] {
Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG
}, 200);
}
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
while (c.moveToNext()) {
String num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); // for number
String name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME)); // for name
String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION)); // for duration
int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));
Log.e("TEST", num);
}
If you want to get it in list
ArrayList < String > list = new ArrayList < > ();
if (Build.VERSION.SDK_INT >= 23) {
requestPermissions(new String[] {
Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG
}, 200);
}
Uri allCalls = Uri.parse("content://call_log/calls");
Cursor c = managedQuery(allCalls, null, null, null, null);
while (c.moveToNext()) {
String num = c.getString(c.getColumnIndex(CallLog.Calls.NUMBER)); // for number
String name = c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME)); // for name
String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION)); // for duration
int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));
list.add(num);
}
final String[] listAccounts = list.toArray(new String[0]);
final int[] currentApp = {
0
};
// Dialog box for multiple card accounts
final AlertDialog.Builder mBuilder = new AlertDialog.Builder(this);
//mBuilder.setTitle("Choose an account :");
mBuilder.setTitle(Html.fromHtml("<font color='#FF7F27'>Num</font>"));
mBuilder.setCancelable(false);
mBuilder.setSingleChoiceItems(listAccounts, 0, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Log.e("Debug_", "Clicked: " + listAccounts[i]);
currentApp[0] = i;
}
});
mBuilder.setPositiveButton("Select", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int which) {
Log.e("Debug_", "Name: " + listAccounts[currentApp[0]] + " Index: " + currentApp[0]);
number.setText(listAccounts[currentApp[0]]);
dialogInterface.dismiss();
}
});
AlertDialog mDialog = mBuilder.create();
mDialog.show();
I have a problem with NFC. Is there any posible way to turn off the NFC sound in Android API 16 and higher?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_traveller_read_tag);
context = this;
tvNFCContent = findViewById(R.id.nfc_contents);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
// Stop here, we definitely need NFC
Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
finish();
}
readFromIntent(getIntent());
pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writeTagFilters = new IntentFilter[]{tagDetected};
findViewById(R.id.menu).setVisibility(View.GONE);
}
private void readFromIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs = null;
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
buildTagViews(msgs);
}
}
private void buildTagViews(NdefMessage[] msgs) {
if (msgs == null || msgs.length == 0) return;
String text = "";
//String tagId = new String(msgs[0].getRecords()[0].getType());
byte[] payload = msgs[0].getRecords()[0].getPayload();
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; // Get the Text Encoding
int languageCodeLength = payload[0] & 0063; // Get the Language Code, e.g. "en"
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
try {
// Get the Text
text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
} catch (UnsupportedEncodingException e) {
Log.e("UnsupportedEncoding", e.toString());
}
int tempCoin = Integer.parseInt( DB.getValue(context, UserValue.KEY_COIN) ) + Integer.parseInt( text );
DB.setValue(context,UserValue.KEY_COIN,String.valueOf(tempCoin));
tvNFCContent.setText("حساب شما " + text +" تومان شارژ شد.");
beep.playBeep(context, beep.TypeBeep.OK);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
finish();
}
},1000);
}
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
readFromIntent(intent);
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}
No, disabling the NFC discovery sound is not possible on Android API level 16. Only the reader-mode API introduced in Android API level 19 allows you to disable the platform sounds normally generated for NFC discovery events:. See NfcAdapter.enableReaderMode and the flag NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS.
This is my approach to use gcm for more than 1000 devices. Is it right that way? As I cannot try it unless I have more than 1000 users so any feedback would be appreciated and most importantly am I checking errors correctly? and updating database in a right way?
public class MessagingEndpoint {
private static final Logger log = Logger.getLogger(MessagingEndpoint.class.getName());
/**
* Api Keys can be obtained from the google cloud console
*/
private static final String API_KEY = System.getProperty("gcm.api.key");
private List<RegistrationRecord> records;
private List<String> getRegistrationId() {
records = ofy().load().type(RegistrationRecord.class).list();
List<String> records_ID = new ArrayList<String>();
for (int i = 0; i < records.size(); i++) {
records_ID.add(records.get(i).getRegId());
}
return records_ID;
}
private List<List<String>> regIdInThousands(List<String> list, final int L) {
List<List<String>> parts = new ArrayList<List<String>>();
final int N = list.size();
for (int i = 0; i < N; i += L) {
parts.add(new ArrayList<String>(list.subList(i, Math.min(N, i + L))));
}
return parts;
}
*
* #param message The message to send
*/
public void sendMessage(#Named("message") String message) throws IOException {
if (message == null || message.trim().length() == 0) {
log.warning("Not sending message because it is empty");
return;
}
// crop longer messages
if (message.length() > 1000) {
message = message.substring(0, 1000) + "[...]";
}
Sender sender = new Sender(API_KEY);
Message msg = new Message.Builder().addData("message", message).build();
List<List<String>> regIdsParts = regIdInThousands(getRegistrationId(), 1000);
for (int i = 0; i < regIdsParts.size(); i++) {
MulticastResult multicastResult = sender.send(msg, regIdsParts.get(i), 5);
if (multicastResult.getCanonicalIds() != 0) {
List<Result> results = multicastResult.getResults();
for (int j = 0; j < results.size(); j++) {
if (results.get(j).getMessageId() != null) {
log.info("Message sent to " + regIdsParts.get(i).get(j));
String canonicalRegId = results.get(j).getCanonicalRegistrationId();
if (canonicalRegId != null) {
// if the regId changed, we have to update the datastore
log.info("Registration Id changed for " + regIdsParts.get(i).get(j) + " updating to " + canonicalRegId);
regIdsParts.get(i).set(j, canonicalRegId);
ofy().save().entity(records.get((i*1000)+j)).now();
} else {
String error = results.get(j).getErrorCodeName();
if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
log.warning("Registration Id " + regIdsParts.get(i).get(j) + " no longer registered with GCM, removing from datastore");
// if the device is no longer registered with Gcm, remove it from the datastore
ofy().delete().entity(records.get((i*1000)+j)).now();
} else {
log.warning("Error when sending message : " + error);
}
}
}
}
}
}
}
}
Your code looks good, Only thing I can notice is its quite verbose and complicated. You can take a look at this one just as a option if you are considerate about error handling:
public void sendMessageToMultipleDevices(String key, String value, ArrayList devices) {
Sender sender = new Sender(myApiKey);
Message message = new Message.Builder().addData(key, value).build();
try {
MulticastResult result = sender.send(message, devices, 5);
MTLog.info(TAG, "result " + result.toString());
for (int i = 0; i < result.getTotal(); i++) {
Result r = result.getResults().get(i);
if (r.getMessageId() != null) {
String canonicalRegId = r.getCanonicalRegistrationId();
if (canonicalRegId != null) {
// devices.get(i) has more than on registration ID: update database
}
} else {
String error = r.getErrorCodeName();
if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
// application has been removed from devices.get(i) - unregister database
}
}
}
} catch (IOException ex) {
MTLog.err(TAG, "sending message failed", ex);
}
}
Hi I am trying to send sms to different mobile numbers with different text body, my code is also sending sms more than 160 characters but it sends to only one number not to all , Now I want to send multiparttext message to all contact list.pls help
private void sendSMS()
{
if (list_phone.size()!=0){
//new AddNewCategory().execute();
for (i = 0; i < len; i++){
SmsManager sm = SmsManager.getDefault();
ArrayList<String> message_parts = sm.divideMessage(list_MESSAGE_BODY.get(i));
// Log.e("Message parts 3", message_parts.get(3));
// Log.e("Message parts 4", message_parts.get(4));
Intent iSent = new Intent();
PendingIntent piSent = PendingIntent.getBroadcast(this, 0, iSent, 0);
Intent iDel = new Intent();
PendingIntent piDel = PendingIntent.getBroadcast(this, 0, iDel, 0);
if (message_parts.size() == 1)
{
String msg = message_parts.get(0);
sm.sendTextMessage(list_phone.get(i), null, msg, piSent, piDel);
Toast.makeText(getApplicationContext(), " Message sent", Toast.LENGTH_SHORT).show();
}
else
{
ArrayList<PendingIntent> sentPis = new ArrayList<PendingIntent>();
ArrayList<PendingIntent> delPis = new ArrayList<PendingIntent>();
int ct = message_parts.size();
for (int i = 0; i < ct; i++)
{
sentPis.add(i, piSent);
delPis.add(i, piDel);
}
//Log.e("Message Parts", message_parts+"");
Log.e("Phone list", list_phone.get(i));
Log.e("Message parts"+i, message_parts.get(i));
sm.sendMultipartTextMessage(list_phone.get(i), null, message_parts, sentPis, delPis);
Toast.makeText(getApplicationContext(), " Message sent", Toast.LENGTH_SHORT).show();
}
}
else
{
// Toast.makeText(getApplicationContext(), "Phone list is empty.. Message not sent", Toast.LENGTH_SHORT).show();
}
}
you need added ";" after each number.
I give one example , Please check it and give your problem solution.
protected void sendMsg(Context context, SmsMessage smsMessage) {
SmsManager smsMgr = SmsManager.getDefault();
ArrayList<string> smsMessageText = smsMgr.divideMessage(smsMessage.getMsgBody());
PendingIntent sentPI = PendingIntent.getBroadcast(context, 0, new Intent("SMS_SENT"), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(context, 0, new Intent("SMS_DELIVERED"), 0);
int AddresseesPerMessage = 10;
StringBuilder builder = new StringBuilder();
String delim = "";
for (ContactItem c:smsMessage.getAddresseeList()) {
// For every phone number in our list
builder.append(delim).append(c.getPhoneNumber().toString());
delim=";"; /// if have SAMSUNG devices then delim=", ";
if (((smsMessage.getAddresseeList().indexOf(c)+1) % AddresseesPerMessage) == 0 || smsMessage.getAddresseeList().indexOf(c)+1 == smsMessage.getAddresseeList().size()) {
// using +1 because index 0 mod 9 == 0
for(String text : smsMessageText){
// Send 160 bytes of the total message until all parts are sent
smsMgr.sendTextMessage(builder.toString(), null, text, sentPI, deliveredPI);
}
builder.setLength(0);
delim="";
}
}
}
Try this code
{
if (list_phone.size()!=0){
//new AddNewCategory().execute();
for (i_m = 0; i_m < len; _mi++){
SmsManager sm = SmsManager.getDefault();
ArrayList<String> message_parts = sm.divideMessage(list_MESSAGE_BODY.get(i_m));
// Log.e("Message parts 3", message_parts.get(3));
// Log.e("Message parts 4", message_parts.get(4));
Intent iSent = new Intent();
PendingIntent piSent = PendingIntent.getBroadcast(this, 0, iSent, 0);
Intent iDel = new Intent();
PendingIntent piDel = PendingIntent.getBroadcast(this, 0, iDel, 0);
if (message_parts.size() == 1)
{
String msg = message_parts.get(0);
sm.sendTextMessage(list_phone.get(i), null, msg, piSent, piDel);
Toast.makeText(getApplicationContext(), " Message sent", Toast.LENGTH_SHORT).show();
}
else
{
ArrayList<PendingIntent> sentPis = new ArrayList<PendingIntent>();
ArrayList<PendingIntent> delPis = new ArrayList<PendingIntent>();
int ct = message_parts.size();
for (int i_t = 0; i_t < ct; i_t++)
{
sentPis.add(i_t, piSent);
delPis.add(i_t, piDel);
}
//Log.e("Message Parts", message_parts+"");
Log.e("Phone list", list_phone.get(i));
Log.e("Message parts"+i, message_parts.get(i_m));
sm.sendMultipartTextMessage(list_phone.get(i), null, message_parts, sentPis, delPis);
Toast.makeText(getApplicationContext(), " Message sent", Toast.LENGTH_SHORT).show();
}
}
else
{
// Toast.makeText(getApplicationContext(), "Phone list is empty.. Message not sent", Toast.LENGTH_SHORT).show();
}
}
I have a webservice and I am using ksoap2 to connect to it and upload some pictures.
The process is:
Open the gallery
Select a few pictures
Share to my app
Start a foreground service
send the basic information to this service, like an array with all the picture's path
handle the intent and take the bundles
and start the foreground notification with the proper flag and with startForeground(id,noty)
The problem:
Everything goes right. Uploading and showing the items uploaded ...until...suddenly the notification just disappear from the bar.
After a while it shows by itself again and continues the upload, I tried to set some stuff to get the last item uploaded and start from there, I don't know if I am doing right and I would like to have an advice about this.
This is the Activity from where I call the Service:
Intent mServiceIntent = new Intent(this, UploadService.class);
Bundle bund = new Bundle();
bund.putStringArray("pathList", pictureList);
bund.putString("tags", tag);
boolean hasGeotag = UserManagerClass.UserLogged.isActiveLocation();
bund.putBoolean("hasGeotag", hasGeotag);
if (hasGeotag) {
GeoTag gtag = UserManagerClass.UserLocation;
bund.putDouble("latitude", gtag.getLatitude());
bund.putDouble("longitude", gtag.getLongitude());
bund.putString("city", gtag.getCity());
bund.putString("country", gtag.getCountry());
bund.putString("address", gtag.getAddress());
}
bund.putInt("idOwner", IDOWNER);
bund.putInt("idUser", UserManagerClass.UserLogged.getID());
bund.putInt("albumindex", albumIndex);
bund.putInt("privacyindex", privacyIndex);
bund.putString("comment", comment);
mServiceIntent.putExtras(bund);
startService(mServiceIntent);
and this is the code of the Service:
public class UploadService extends Service {
private static final int myID = 1433;
private static final String PREF_NAME = "SERVICEUPLOAD";
private static final String UPLOADED_PATH = "UPLOADED_";
private static int position;
private int albumIndex;
private String comment;
private boolean hasGeotag;
private int idOwner;
private int idUser;
private GeoTag location;
private String[] pathList;
private int privacyIndex;
private SoapPost sp;
private String tags;
private NotificationManager nManager;
private PendingIntent pi;
#Override
public void onCreate() {
Log.e("step 1", "entered to create");
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
private void exit() {
Log.e("step 10", "ending...");
deletePosition();
Log.e("step 12", "ended");
this.stopForeground(true);
updateNotification(true);
}
void createNotification() {
Log.e("step 4", "entered to create notification");
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = getText(R.string.upload_waiting);
//
pi = PendingIntent.getActivity(this, 0, new Intent(), Notification.FLAG_FOREGROUND_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.add_comment_icon);
builder.setTicker(text);
builder.setContentIntent(pi);
builder.setContentText(text);
builder.setContentTitle(text);
startForeground(myID, builder.build());
}
private void updateNotification(boolean completed) {
Log.e("step 8", "updating notification");
String ticker = String.format(getResources().getString(R.string.upload_uploading_tick), position);
String message = String.format(getResources().getString(R.string.upload_uploading_message_progress), position, pathList.length);
String title = String.format(getResources().getString(R.string.upload_uploading_title), position);
String title_completed = getResources().getString(R.string.upload_uploading_title_completed);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.add_comment_icon);
builder.setContentText(message);
builder.setTicker(ticker);
if (!completed)
builder.setContentTitle(title);
else {
builder.setContentTitle(title_completed);
pi = PendingIntent.getActivity(this, 0, new Intent(), 0);
}
builder.setContentIntent(pi);
if (completed)
nManager.notify(myID, builder.build());
else
startForeground(myID, builder.build());
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("step 2", "entered to onstart");
handleIntent(intent);
return START_STICKY;
}
void handleIntent(Intent data) {
Log.e("step 3", "entered to handle");
// GETS THE POSITIONS IF THE SERVICE WAS STOPPED BEFORE
// RETURN 0 IF IT WASNT
getPosition();
//
if (data == null)
this.stopForeground(true);
Bundle dt = data.getExtras();
tags = dt.getString("tags");
pathList = dt.getStringArray("pathList");
hasGeotag = dt.getBoolean("hasGeotag");
if (hasGeotag) {
location = new GeoTag();
location.setLatitude(dt.getDouble("latitude"));
location.setLongitude(dt.getDouble("longitude"));
location.setAddress(dt.getString("address"));
location.setCity(dt.getString("city"));
location.setCountry(dt.getString("country"));
}
idOwner = dt.getInt("idOwner");
idUser = dt.getInt("idUser");
albumIndex = dt.getInt("albumindex");
privacyIndex = dt.getInt("privacyindex");
comment = dt.getString("comment");
// isCover = dt.getBoolean("isCover");
sp = new SoapPost();
// CREATES THE NOTFICATION
createNotification();
// FINALLY SEND THE DATA TO THE WEB SERVICE
sendData();
}
private void sendData() {
Log.e("step 4", "entered to send data");
for (String fl : pathList) {
Log.e("step 5", "sending... " + fl);
if (fl != null && !fl.equals(UPLOADED_PATH)) {
try {
String[] dataup = new String[10];
if (hasGeotag) {
dataup = new String[15];
dataup[10] = String.valueOf(location.getLatitude());
dataup[11] = String.valueOf(location.getLongitude());
dataup[12] = location.getAddress();
dataup[13] = location.getCity();
dataup[14] = location.getCountry();
}
if (comment.length() > 0)
dataup[0] = URLEncoder.encode(comment, "UTF-8");
else
dataup[0] = "";
dataup[1] = String.valueOf(idOwner);
dataup[2] = String.valueOf(idUser);
dataup[3] = "2";
dataup[4] = "";
dataup[5] = String.valueOf(albumIndex);
dataup[6] = String.valueOf(privacyIndex);
dataup[7] = "";
dataup[8] = "";
dataup[9] = "";
File file = new File(fl);
// CONTINUE ONLY IF THE FILE EXISTS
if (file.exists()) {
Log.e("step 6", "file exists true");
// SETTING WIDTH AND HEIGHT
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fl, options);
int wth = options.outWidth;
int hth = options.outHeight;
long lenght = file.length();
// END W AND H
String b64 = null;
b64 = Base64.encodeToString(PictureManagerClass.getBytesFromFile(file), Base64.DEFAULT);
file = null;
// SETTING
// 4 BASE64
// 7 W
// 8 H
// 9 L
dataup[4] = b64;
dataup[7] = String.valueOf(wth);
dataup[8] = String.valueOf(hth);
dataup[9] = String.valueOf(lenght);
Log.e("step 7", "uploading... " + fl);
// SET THE CURRENT ITEM AS UPLOADED
pathList[position] = null;
// SAVE THE ACTUAL POSITION
savePosition();
sp.uploadPicture(dataup, tags, SoapPost.UPLOAD_PICTURE);
position++;
updateNotification(false);
}// END FILE EXISTS
}
catch (Exception ex) {
// SAVE THE ACTUAL POSITION
savePosition();
//
StackTraceElement[] stack = ex.getStackTrace();
String Trace = " ";
for (StackTraceElement line : stack) {
Trace += line.toString();
}
Log.e("SERVICE: ", Trace);
}
}// END FL NULL
}// END FOR
exit();
}
#Override
public void onDestroy() {
// SAVE THE ACTUAL POSITION
savePosition();
super.onDestroy();
}
#Override
public void onLowMemory() {
// SAVE THE ACTUAL POSITION
savePosition();
super.onLowMemory();
}
void savePosition() {
Log.e("step 9", "saving position");
// SET THE VALUES FROM PATHS TO SET TO SAVE IT INTO PREFERENCES
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("position", position);
Set<String> set = new HashSet<String>();
if (pathList != null) {
for (int i = 0; i < position; i++)
pathList[i] = null;
for (int i = position; i < pathList.length; i++)
if (pathList[i] != null)
set.add(pathList[i]);
}
if (pathList != null)
editor.putStringSet("pathList", set);
editor.commit();
}
void getPosition() {
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
position = prefs.getInt("position", 0);
Log.e("step 3.1", position + "");
Set<String> set = new HashSet<String>();
set = prefs.getStringSet("pathList", set);
int pos = 0;
for (String path : set) {
pathList = new String[set.size()];
pathList[pos] = path;
pos++;
}
}
void deletePosition() {
Log.e("step 11", "clear...");
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.clear();
editor.commit();
}
/* (non-Javadoc)
* #see android.app.Service#onBind(android.content.Intent)
*/
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
FIXED
i fixed it...this is the new method sendData():
private void sendData() {
new Thread(new Runnable() {
#Override
public void run() {
for (String fl : pathList) {
if (fl != null && !fl.equals(UPLOADED_PATH)) {
try {
String[] dataup = new String[10];
if (hasGeotag) {
dataup = new String[15];
dataup[10] = String.valueOf(location.getLatitude());
dataup[11] = String.valueOf(location.getLongitude());
dataup[12] = location.getAddress();
dataup[13] = location.getCity();
dataup[14] = location.getCountry();
}
if (comment.length() > 0)
dataup[0] = URLEncoder.encode(comment, "UTF-8");
else
dataup[0] = "";
dataup[1] = String.valueOf(idOwner);
dataup[2] = String.valueOf(idUser);
dataup[3] = "2";
dataup[4] = "";
dataup[5] = String.valueOf(albumIndex);
dataup[6] = String.valueOf(privacyIndex);
dataup[7] = "";
dataup[8] = "";
dataup[9] = "";
File file = new File(fl);
// CONTINUE ONLY IF THE FILE EXISTS
if (file.exists()) {
// SETTING WIDTH AND HEIGHT
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fl, options);
int wth = options.outWidth;
int hth = options.outHeight;
long lenght = file.length();
// END W AND H
byte[] pic = PictureManagerClass.getBytesFromFile(file);
Log.e("picLength", pic.length + "");
file = null;
// SETTING
// 4 BASE64
// 7 W
// 8 H
// 9 L
dataup[4] = "";
dataup[7] = String.valueOf(wth);
dataup[8] = String.valueOf(hth);
dataup[9] = String.valueOf(lenght);
Log.e("step 7", "uploading... " + fl);
// SET THE CURRENT ITEM AS UPLOADED
pathList[position] = null;
// SAVE THE ACTUAL POSITION
savePosition();
String mes = sp.uploadPicture(dataup, tags, SoapPost.UPLOAD_PICTURE, pic);
Log.e("picID", mes);
pic = null;
dataup = null;
position++;
updateNotification(false);
Thread.sleep(1 * 1000);
}// END FILE EXISTS
}
catch (Exception ex) {
// SAVE THE ACTUAL POSITION
savePosition();
//
StackTraceElement[] stack = ex.getStackTrace();
String Trace = " ";
for (StackTraceElement line : stack) {
Trace += line.toString();
}
Log.e("SERVICE: ", Trace);
}
}// END FL NULL
}// END FOR
exit();
}
}).start();;
}
and now the notification doesnt hide until all files were uploaded ... thanks.