I have a broadcast receiver that on boot of the phone runs a pending intent. The pending intent opens a dialog box to alert the user.
I noticed that if there are several dialog boxes who's time has passed, they all fire off at once. Which leads to only the first dialog box displayed. When you click on the 'dismiss' button the it dismisses all the dialog boxes.
Is there a way to for each box to be displayed one at a time and not jam up like this?
I read up on using 'synchronize' but it seems to be only used in networking. Can you let me know what would be the best approach to resolving this issue?
My code:
package com.google.android.gcm.demo.app.Alerts;
import java.io.IOException;
import com.google.android.gcm.demo.app.DemoActivity;
import com.google.android.gcm.demo.app.PreferenceConnector;
import com.google.android.gcm.demo.app.R;
import com.google.android.gcm.demo.app.TabBarExample;
import com.google.android.gcm.demo.app.sqllite.DatabaseSqlite;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
public class AlertDialogActivity extends Activity {
MediaPlayer player = new MediaPlayer();
Bundle bundle;
Vibrator vibrate;
DatabaseSqlite entry = new DatabaseSqlite(AlertDialogActivity.this);
int vibrateState;
int soundState;
AlertDialog.Builder builder;
Intent intent;
int idInteger;
int alertDismissed = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bundle = getIntent().getExtras();
String name = bundle.getString("name");
String id = bundle.getString("id");
idInteger = Integer.parseInt(id);
intent = new Intent(AlertDialogActivity.this, TabBarExample.class);
sound();
vibrate();
entry.open();
entry.updateAlertDismissedState(idInteger, alertDismissed);
String text = entry.getMinutesForOneShot(idInteger);
entry.close();
String textForDisplay = "In " + text + " Minutes";
builder = new AlertDialog.Builder(this);
builder.setMessage(textForDisplay)
.setTitle(name)
.setCancelable(false)
.setNegativeButton("Dismiss",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
soundState = PreferenceConnector.readInteger(
AlertDialogActivity.this,
PreferenceConnector.SOUND_ON_OFF, 0);
if (soundState == 0) {
player.pause();
player.release();
}
vibrateState = PreferenceConnector.readInteger(
AlertDialogActivity.this,
PreferenceConnector.VIBRATE_ON_OFF, 0);
if (vibrateState == 0) {
vibrate.cancel();
}
startActivity(intent);
}
});
AlertDialog alert = builder.create();
alert.show();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
private void sound() {
soundState = PreferenceConnector.readInteger(AlertDialogActivity.this,
PreferenceConnector.SOUND_ON_OFF, 0);
if (soundState == 0) {
// play sound
AssetFileDescriptor afd = this.getResources().openRawResourceFd(
R.raw.alarm_clock);
try {
player.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
afd.close();
player.setAudioStreamType(AudioManager.STREAM_ALARM);
player.setLooping(true);
player.prepare();
player.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
}
}
private void vibrate() {
vibrateState = PreferenceConnector
.readInteger(AlertDialogActivity.this,
PreferenceConnector.VIBRATE_ON_OFF, 0);
if (vibrateState == 0) {
// Get instance of Vibrator from current Context
vibrate = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Start immediately
// Vibrate for 200 milliseconds
// Sleep for 500 milliseconds
long[] pattern = { 0, 200, 500 };
// The "0" means to repeat the pattern starting at the beginning
// CUIDADO: If you start at the wrong index (e.g., 1) then your
// pattern will be off --
// You will vibrate for your pause times and pause for your vibrate
// times !
vibrate.vibrate(pattern, 0);
} else {
}
}
}
In order to resolve this issue, I compared the current date to when the alert fired off. If the alert passed I, I put it in an arrary list. Then I used a intent to send the list to another activity. In that activity, I used a another for loop to process the dialog boxes one at a time.
Related
I've developed a version of the native SIP Demo app provided by Google https://android.googlesource.com/platform/development/+/master/samples/SipDemo/
My Simple app registers with the SIP server and when a call invite is received on that SIP account a notification and Toast is displayed with the caller ID. I've not designed the app to run as a service or anything. After launching the activity the app registers with the SIP server and then I simple hit the home button and let the app run in the background, waiting for an incoming call.
The app functions correctly it's just that within ~ 12 - 24 hrs the app seems to have been stopped by the Android OS. I'm not sure if it's related to the native SIP stack or Android's resource manager shutting down the app but I've tried setting everything I can on the handset itself to prevent the app from being stopped like removing any battery saving settings etc.
Are there any tips to keep the app running in the background using the native SIP API?
My is code below:
CallerIDActivity.java -
package example.callerid;
//This app has been developed with a target API of 22 so as to avoid having to
//implement runtime permissions on the test handset with a higher API level.
import android.Manifest;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.sip.SipException;
import android.net.sip.SipManager;
import android.net.sip.SipProfile;
import android.net.sip.SipRegistrationListener;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
public class CallerIDactivity extends Activity {
public SipManager manager = null;
public SipProfile me = null;
public IncomingCallReceiver callReceiver;
public CallerIDactivity (){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createNotificationChannel();
}//end constructor
//define NotificationChannel method for use in the contructor above
//IncomingCallReciever will then use this channel to send notification of CID
public void createNotificationChannel(){
//Create the Notification but only on API 26+ as the
//notification class is new and not in the support lib
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
CharSequence name = "CHANNEL_NAME";
String description = "CID_NOTIFY";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel("CHANNEL_ID", name, importance);
channel.setDescription(description);
//Register the channel with the system: you can't change the importance
//or other notification behaviour after this
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if(notificationManager !=null) {
notificationManager.createNotificationChannel(channel);
}
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.callerid);
// Set up the intent filter. This will be used to trigger an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.CallerID.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
}//end onCreate
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
Log.d("CallerID", "UnRegisteringReceiverOnDestroy ");
Toast toast = Toast.makeText(getApplicationContext(), "UnRegisteringReceiverOnDestroy", Toast.LENGTH_LONG);
toast.show();
}
}//end onDestroy
public void RegisterBtn(View callerid){
initializeManager();
Log.d("CallerIDactivity","RegisterBtn Press");
Toast toast = Toast.makeText(getApplicationContext(),"Registering", Toast.LENGTH_SHORT);
toast.show();
}
public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
public void initializeLocalProfile() {
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
try {
SipProfile.Builder builder = new SipProfile.Builder("sipaccount", "my.sip.server");
builder.setPassword("pass");
me = builder.build();
Intent i = new Intent();
i.setAction("android.CallerID.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me,pi,null);
// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
}catch (ParseException pe) {
updateStatus("Connection Error.");
} catch (SipException se) {
updateStatus("Connection error.");
}
}
/**
* Closes out your local profile, freeing associated objects into memory
* and unregistering your device from the server.
*/
public void closeLocalProfile() {
if (manager == null) {
Log.d("closeLocalProfile", "manager == null");
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
Toast toast = Toast.makeText(getApplicationContext(), "ClosingProfileURI"+" "+me.getUriString(), Toast.LENGTH_SHORT);
toast.show();
}
} catch (Exception ee) {
Toast toast = Toast.makeText(getApplicationContext(), ee.getMessage(), Toast.LENGTH_SHORT);
toast.show();
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
/**
* Updates the status box at the top of the UI with a messege of your choice.
* #param status The String to display in the status box.
*/
public void updateStatus(final String status) {
this.runOnUiThread(new Runnable() {
public void run() {
Toast toast = Toast.makeText(getApplicationContext(), status, Toast.LENGTH_SHORT);
toast.show();
}});
/* Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
Log.i("allenssip",status);
TextView labelView = (TextView) findViewById(R.id.sipLabel);
labelView.setText(status);
}
});
*/
}//end updateStatus
}//end Class
IncomingCallReceiver.java -
package example.callerid;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.sip.*;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
/**
* Listens for incoming SIP calls, intercepts and hands them off to CallerIDactivity.
*/
public class IncomingCallReceiver extends BroadcastReceiver {
public Calendar calendar;
public SimpleDateFormat dateFormat;
public String date;
public SipManager mSipManager;
public SipSession mSipSesion;
public SipProfile peerProfile;
static private int notifyNum = 1;
/**
* Processes the incoming call, answers it, and hands it over to the
* CallerIDactivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
mSipManager = SipManager.newInstance(context);
try {
mSipSesion = mSipManager.getSessionFor(intent);
} catch (SipException e) {
e.printStackTrace();
}
peerProfile = mSipSesion.getPeerProfile();
calendar = Calendar.getInstance();
dateFormat = new SimpleDateFormat("dd/MM/yyyy");
date = dateFormat.format(calendar.getTime());
Log.d("CallerID", "OnReceive");
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, "CHANNEL_ID")
.setSmallIcon(R.mipmap.ic_launcher_round)
.setContentTitle("CallerID" + " " + date)
.setContentText(peerProfile.getDisplayName())
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if(notifyNum <= 9) {
notificationManager.notify(notifyNum++, mBuilder.build());
}else {notificationManager.notify(notifyNum, mBuilder.build());
notifyNum = 1;
}
int count = 0;
while (count <= 10) {
Toast toast = Toast.makeText(context, peerProfile.getDisplayName(), Toast.LENGTH_SHORT);
toast.show();
count++;
}//end while
}//end onReceive
}//end Class
i have for the passed 4 days tried to upload to youtube videos but i have failed please help me .
package com.example.testyoutube;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.media.MediaFileSource;
import com.google.gdata.data.media.mediarss.MediaCategory;
import com.google.gdata.data.media.mediarss.MediaDescription;
import com.google.gdata.data.media.mediarss.MediaKeywords;
import com.google.gdata.data.media.mediarss.MediaTitle;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.YouTubeMediaGroup;
import com.google.gdata.data.youtube.YouTubeNamespace;
import com.google.gdata.util.AuthenticationException;
import com.google.gdata.util.ServiceException;
public class MainActivity extends Activity {
private Button button;
private YouTubeService service;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
submitVideo("/storage/emulated/0/Pictures/Hello Camera/VID_20140523_204750.mp4",
"i have done it ", "Yooooooooo , it works", "fun");
}
});
}
public void submitVideo(String vName, String vTitle, String vDesc, String vCate) {
String developer_key = "api key"; // Registered developer key
String clientID = "gmailaccount"; // Server's Youtube account
String password = "passwordofgmailaccount"; // Server's Youtube password
service = new YouTubeService(clientID, developer_key); // YouTube Object, we take action by this.
try {
service.setUserCredentials(clientID,password);
} catch (AuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
File videoFile = new File( vName ); // The video local file prepare to upload
String VIDEO_UPLOAD_FEED = "http://uploads.gdata.youtube.com/feeds/api/users/default/uploads";
String mediaType = "video/*"; // Serach .flv MIME type may found more
String vKey1 = vCate; // Use same category and keyword
VideoEntry newEntry = new VideoEntry(); // YouTube video object type, they will return this after uploaded
YouTubeMediaGroup mg = newEntry.getOrCreateMediaGroup(); // Collect all of the video information
mg.addCategory(new MediaCategory(YouTubeNamespace.CATEGORY_SCHEME, vCate));
mg.setTitle(new MediaTitle());
mg.getTitle().setPlainTextContent(vTitle);
mg.setDescription(new MediaDescription());
mg.getDescription().setPlainTextContent(vDesc);
mg.setKeywords(new MediaKeywords());
mg.getKeywords().addKeyword(vKey1);
MediaFileSource ms = new MediaFileSource(videoFile, mediaType);
newEntry.setMediaSource(ms);
VideoEntry ve = null;
try {
ve = service.insert(new URL(VIDEO_UPLOAD_FEED), newEntry);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(ve == null){
System.out.println("Submit to youtube fail.");
return ;
}
}
}
it says that this "service = new YouTubeService(clientID, developer_key);" has error but it does not explain why , please help (or suggest another code please)
U can ddo it using Intent
ContentValues content = new ContentValues(4);
content.put(Video.VideoColumns.DATE_ADDED,
System.currentTimeMillis() / 1000);
content.put(Video.Media.MIME_TYPE, "video/mp4");
content.put(MediaStore.Video.Media.DATA, "video_path");
ContentResolver resolver = getBaseContext().getContentResolver();
Uri uri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, content);
Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,"Title");
sharingIntent.putExtra(android.content.Intent.EXTRA_STREAM,uri);
startActivity(Intent.createChooser(sharingIntent,"share:"));
I am a beginner in Android. I want a sample app which uses this library: https://github.com/puelocesar/android-lib-magick. I tried to use https://github.com/lilac/Android-ImageMagick before - I made lots of changes to make it work but the result I got was not satisfactory.
I just want to know which class to call for a particular thing.
These are the effects i am getting using https://github.com/lilac/Android-ImageMagick
blur, charcoal and no effect looks exactly same. when i select edge it shows blur image.
and the noise effects appear but they look like red and green dots are drawn manually on that image.
below is the code which runs application.
it searches for images in sd card with hard coded name and extention. it gets all the ibages but i am unable to understand wha it does with those images because it shows only one image on screen.
also dont know test.txt is created. this code is present in library as AndroidMagickActivity
i did some changes in android.mk file after searching for long time and now its running but the output is not that good.
please anybody help me to improve results of lilac library or help me to understand how to use https://github.com/puelocesar/android-lib-magick
i am beginner and i don't know how to use NDK and how to create JNI and .so files
package magick;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.magick.R;
import magick.util.DisplayImageMetaData;
import magick.util.MagickBitmap;
import android.util.Log;
import android.view.*;
public class AndroidMagickActivity extends Activity {
static final int PROGRESS_DIALOG = 0;
ProgressDialog progressDialog = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// InputStream stream = getResources().openRawResource(R.raw.app_notes);
try {
final MagickImage img = new MagickImage(new ImageInfo("/sdcard/1.jpg"));
/*
* ImageView iv = new ImageView(this);
* iv.setImageBitmap(MagickBitmap.ToBitmap(img));
* setContentView(iv);
*/
// setContentView(R.layout.main);
Spinner s = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this,R.array.effects, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
s.setAdapter(adapter);
s.setOnItemSelectedListener(new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
ProgressThread t = new ProgressThread(img, pos);
//runOnUiThread(t);
t.run();
}
public void onNothingSelected(AdapterView<?> parent) {
// Do nothing.
}
});
ImageView iv = (ImageView) findViewById(R.id.imageView);
iv.setImageBitmap(MagickBitmap.ToBitmap(img));
} catch (MagickApiException e) {
e.printStackTrace();
} catch (MagickException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*
* TextView tv = new TextView(this);
* tv.setText(DisplayImageMetaData.displayMagickImage(img));
* setContentView(tv);
*/
int count = 2;
MagickImage images[] = new MagickImage[count];
for (int i = 0; i < count; i++) {
String path = "/sdcard/" + String.valueOf(i + 1) + ".jpg";
try {
images[i] = new MagickImage(new ImageInfo(path));
} catch (MagickException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
MagickImage image = new MagickImage(images);
image.setImageFormat("gif");
String fn = Environment.getExternalStorageDirectory() + "/Pictures/test.gif";
image.setFileName(fn);
ImageInfo info = new ImageInfo(fn);
info.setMagick("gif");
//image.writeImage(info);
byte blob[] = image.imageToBlob(info);
FileOutputStream fos = new FileOutputStream(fn);
fos.write(blob);
fos.close();
FileOutputStream testOS = new FileOutputStream("/mnt/sdcard/test.txt");
testOS.write("abc".getBytes());
testOS.close();
} catch (MagickException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected Dialog onCreateDialog(int id, Bundle bundle) {
switch (id) {
case PROGRESS_DIALOG:
/*
* ProgressDialog dialog =
* ProgressDialog.show(AndroidMagickActivity.this, "",
* "Loading. Please wait...", true);
*/
progressDialog = new ProgressDialog(AndroidMagickActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("Loading...");
return progressDialog;
// return dialog;
default:
return null;
}
}
/** Nested class that performs progress calculations (counting) */
private class ProgressThread extends Thread {
MagickImage img;
int pos;
ProgressThread(MagickImage image, int pos) {
this.img = image;
this.pos = pos;
}
public void run() {
int effect = 0;
AndroidMagickActivity.this.showDialog(PROGRESS_DIALOG);
switch (pos) {
case 1:
effect = NoiseType.UndefinedNoise;
break;
case 2:
effect = NoiseType.UniformNoise;
break;
case 3:
effect = NoiseType.GaussianNoise;
break;
case 4:
effect = NoiseType.MultiplicativeGaussianNoise;
break;
case 5:
effect = NoiseType.ImpulseNoise;
break;
case 6:
effect = NoiseType.LaplacianNoise;
break;
case 7:
effect = NoiseType.PoissonNoise;
break;
}
Bitmap bitmap = null;
try {
ImageView iv = (ImageView) findViewById(R.id.imageView);
MagickImage image = null;
if (pos < 8)
image = img.addNoiseImage(effect);
else if (pos == 9)
image = img.blurImage(5, 1);
else if (pos == 10)
image = img.charcoalImage(5, 1);
else if (pos == 11)
image = img.edgeImage(0);
if (image != null) {
bitmap = MagickBitmap.ToBitmap(image);
iv.setImageBitmap(bitmap);
}
// bitmap.recycle(); we can't do that.
AndroidMagickActivity.this.dismissDialog(PROGRESS_DIALOG);
} catch (MagickException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
In my application i want to do bluetooth chat. I'm facing a problem in threading. In my application my android phone will work as server which has a blocking statement
socket=mServerSocket.accept();
for this purpose i've created a child thread so that it will run separately. But before finishing this child thread main thread goes down giving Force Close and if i use the .join() method it hangs up my UI.
What is the solution to run both threads parallel?
this is my code
main Activity
package com.my.bluechat_2_1;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class BlueChat extends Activity {
/** Called when the activity is first created. */
private BlueHandler btHandler=null;
private BluetoothAdapter btAdapter = null;
private Context context=this;
TextView chatWindow=null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
chatWindow=(TextView)findViewById(R.id.textView1);
doStart();
}
private void doStart(){
Button btnStart=(Button)findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Get local Bluetooth adapter
btAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if(btAdapter == null)
{
Toast.makeText(context, "Device does not support Bluetooth", Toast.LENGTH_LONG).show();
}
if (!btAdapter.isEnabled()) {
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
chatWindow.append("Waiting for connection...\n");
btHandler=new BlueHandler(context,chatWindow,btAdapter);
Thread acceptThread=new Thread(btHandler);
acceptThread.start();
}
});
}
}
BlueHandler
package com.my.bluechat_2_1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.widget.TextView;
import android.widget.Toast;
public class BlueHandler implements Runnable{
// Name for the SDP record when creating server socket
private static final String SMARTCAM_BT_SERVICE_NAME = "SmartCam";
// Unique UUID for this application
private static final UUID SMARTCAM_BT_SERVICE_UUID = UUID.fromString("95b82690-4c94-11e1-b86c-0800200c9a66");
private BluetoothAdapter btAdapter = null;
private BluetoothServerSocket btServerSocket = null;
private BluetoothSocket btSocket = null;
private InputStream btInputStream=null;
private Context contextObj=null;
private TextView textView;
public BlueHandler(Context contextObj,TextView textView,BluetoothAdapter btAdapter){
this.contextObj=contextObj;
this.btAdapter=btAdapter;
this.textView=textView;
try {
btServerSocket=this.btAdapter.listenUsingRfcommWithServiceRecord(SMARTCAM_BT_SERVICE_NAME, SMARTCAM_BT_SERVICE_UUID);
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(this.contextObj, "Service not created", Toast.LENGTH_LONG);
}
}
#Override
public void run() {
// TODO Auto-generated method stub
textView.append("Inside child thread.\n");
textView.append(btServerSocket+"\n");
while (true) {
try {
btSocket = btServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (btSocket != null) {
// Do work to manage the connection (in a separate thread)
try {
btServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
textView.append("Connected.\n");
try {
btInputStream=btSocket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] buffer = new byte[1024]; // buffer store for the stream
String s;
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes=btInputStream.read(buffer);
s= new String(buffer);
// Send the obtained bytes to the UI Activity
textView.append("received ::" +s+"\n");
} catch (IOException e) {
break;
}
}
}
}
You're probably getting a crash because you're accessing a textView on the worker thread. You'll need to use TextView.post(Runnable) to make that not happen.
In reality you should be using a bindable Service to do this kind of work. You can post back to the UI via broadcast intents or callback methods, That way you don't have to worry about rotation bugs.
Are you performing a long operation in the constructor of your children thread? Each long operation must be done in the run() method.
I have a login page, it works fine when i put correct username and password but for login failure its not working how to handle this.
In android i don't have any idea if any one can provide code please
here is my code :
package com.android;
import java.io.IOException;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import org.json.JSONException;
import org.json.JSONObject;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.SoapFault;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.AndroidHttpTransport;
import org.xmlpull.v1.XmlPullParserException;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.*;
public class Login extends Activity {
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL ="http:.asmx?op=LoginRequest";
private static final String SOAP_ACTION = "http://tempuri.org/Login";
//private String login="";
private static final String METHOD_NAME = "Login";
ImageButton login_button,sign_button;
TextView m,p,f,email,password,forgot_password;
EditText emailid,epassword;
AlertDialog authProgressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.login);
email=(TextView)findViewById(R.id.email);
password=(TextView)findViewById(R.id.password);
forgot_password=(TextView)findViewById(R.id.forgot);
Context context = email.getContext();
Typeface font=Typeface.createFromAsset(context.getAssets(),"arial.ttf");
email.setTypeface(font);
Context con = password.getContext();
Typeface face=Typeface.createFromAsset(con.getAssets(),"arial.ttf");
password.setTypeface(face);
Context con1 = forgot_password.getContext();
Typeface face1=Typeface.createFromAsset(con1.getAssets(),"arial.ttf");
forgot_password.setTypeface(face1);
// new theTask().execute();
login_button=(ImageButton)findViewById(R.id.login);
sign_button=(ImageButton)findViewById(R.id.signup);
login_button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
String username,password;
emailid =(EditText)findViewById(R.id.edemail);
epassword =(EditText)findViewById(R.id.edpassword);
username = emailid.getText().toString();
password = epassword.getText().toString();
showDialog(0);
// TODO Auto-generated method stub
SoapObject request=new SoapObject(NAMESPACE,METHOD_NAME);
String qry="{\"General\":"+"{\"type\": \"Request\","+"\"application\": \"Mmmmm\","+"\"appver\": \"1.0.0\","+"\"phoneDeviceID\": \"123456789\","+"\"deviceType\": \"Android\","+"\"deviceOSVersion\": \"3.0\"},"+"\"Login\":"+"{\"emailID\":"+"\""+username+"\","+"\"password\":"+"\""+password+"\""+"}"+"}";
Log.i("Input",qry);
request.addProperty("JSONRequestString",qry);
SoapSerializationEnvelope envelope=new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet=true;
envelope.bodyOut=request;
envelope.encodingStyle=SoapSerializationEnvelope.ENC2001;
envelope.setOutputSoapObject(request);
AndroidHttpTransport androidHttpTransPort= new AndroidHttpTransport(URL);
try
{
try {
androidHttpTransPort.call(SOAP_ACTION,envelope);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
SoapPrimitive rest=(SoapPrimitive)envelope.getResponse();
Log.i("output","Result"+rest );
// SoapObject var = (SoapObject)rest.getProperty(0);
String conv=rest.toString();
JSONObject js=new JSONObject(conv);
String login = js.getString("Login");
JSONObject err=new JSONObject(login);
String messcode=js.getString("HomePageFooterNewUpdates");
JSONObject code=new JSONObject(messcode);
int GetMessageCode=code.getInt("noOfMail");
Log.i("message code ","is " +GetMessageCode);
// String errc=err.getString("errorMsg");
// Log.i("err",errc);
int ResponseForLogin=err.getInt("errorCode");
Log.i("Response ","is "+ResponseForLogin);
if(ResponseForLogin==000){
Toast.makeText(Login.this, "Login Successfull", Toast.LENGTH_LONG).show();
// prepare the dialog box
/* ProgressDialog dialog = new ProgressDialog(this);
// make the progress bar Cancelable
dialog.setCancelable(true);
// set a message text
dialog.setMessage("Loading...");
// show it
dialog.show();*/
Intent i=new Intent(Login.this,Home.class);
i.putExtra("messcode", GetMessageCode);
startActivity(i);
} else {
Toast.makeText(Login.this, "Invalid Emailid or Password...Please Try Again", Toast.LENGTH_LONG).show();
}
}catch (XmlPullParserException e) {
e.printStackTrace();
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SoapFault e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} );
sign_button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Intent i=new Intent(Login.this, Signup.class);
startActivity(i);
}
});
}
}
Thanks in advance...
Just giving you few hints , try to take help from this.
ImageButton login=(ImageButton)findViewById(R.id.Login);
EditText editText1=(EditText)findViewById(R.id.emailText);
EditText editText2=(EditText)findViewById(R.id.passwordText);
login.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if((editText1.getText()+" ").trim().equals("") || editText1.getText() == null || (editText2.getText()+" ").trim().equals("") || editText2.getText() == null ){
//show error message here
}
else{
//perrform your action here
//either start a new activity or do something else
}
}
});
Hope this will help you.
I have found the following tutorial which has definitely helped me implement the correct login and registration screens using these resources:
Material Design
Shared Preferences
PHP scripts
MySQL Database
SQLlite Database
This is the link to the tutorial.
I know this is extremely late but I hope it can help you.