I am working on a project in which I have a TCP connection with a server via Android.
I am using the following code:
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
Socket s;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created", Toast.LENGTH_LONG).show();
Log.d(TAG, "onCreate");
player = MediaPlayer.create(this, R.raw.braincandy);
player.setLooping(false); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped", Toast.LENGTH_LONG).show();
Log.d(TAG, "onDestroy");
player.stop();
try {
s.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d(TAG, "onStart");
player.start();
try {
s = new Socket("192.168.1.54", 64000);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am running the connection as a service.
The real problem is I can make a connection with my Android phone (2.3.7) and with the emulator (2.3.3) but when I want to test in on my tablet (4.0.3), my app always crashes when I want to start the connection.
Can someone help me with this?
Here is the logcat log:
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start service
com.gunther.servicetcp.MyService#412b0a98 with Intent
{ cmp=com.gunther.servicetcp/.MyService }: android.os.NetworkOnMainThreadException
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2376)
at android.app.ActivityThread.access$1900(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.NetworkOnMainThreadException
0at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
at libcore.io.IoBridge.connect(IoBridge.java:112)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.Socket.startupSocket(Socket.java:566)
at java.net.Socket.tryAllAddresses(Socket.java:127)
at java.net.Socket.<init>(Socket.java:177)
at java.net.Socket.<init>(Socket.java:149)
at com.gunther.servicetcp.MyService.onStart(MyService.java:53)
at android.app.Service.onStartCommand(Service.java:438)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2359)
: ... 10 more
You shouldn't do network operations on the main thread. This will lead to your app being unresponsive. Before Honeycomb you could get away with it, but Honeycomb and newer Android versions will check and throw the exception you're getting. See also this page of the Android Developers API
Services's onStart() method runs on the main thread, (yes, services seem to run on the main thread of the application.) so you should fork another thread in the onStart() method and do everything you need to do in that thread.
Related
I am closing an activity via finish().
It works fine on several devices but on a Samsung Galaxy S3 Neo running Android 4.4 I get the following issue:
java.lang.RuntimeException
android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3706)
android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
android.app.ActivityThread.access$1500(ActivityThread.java:169)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1330)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:136)
android.app.ActivityThread.main(ActivityThread.java:5476)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:515)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
dalvik.system.NativeStart.main(Native Method)
Caused by: android.util.Log.println_native(Native Method)
android.util.Log.e(Log.java:307)
com.ads.adstimer.fragment.Registration.RegistrationActivity.onDestroy(RegistrationActivity.java:214)
android.app.Activity.performDestroy(Activity.java:5623)
android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1123)
android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3693)
android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
android.app.ActivityThread.access$1500(ActivityThread.java:169)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1330)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:136)
android.app.ActivityThread.main(ActivityThread.java:5476)
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke(Method.java:515)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
dalvik.system.NativeStart.main(Native Method)
I have found two posts about that subject: First, Second
But they did not help me.
My activity code. Note that I am using AppIntro:
public class RegistrationActivity extends AppIntro {
private AsyncTaskRegisterInBackground registerPushToken;
(...)
#Override
public void onDonePressed() {
(...)
if (regid.isEmpty()) {
registerPushToken = new AsyncTaskRegisterInBackground();
registerPushToken.setParams(activity, gcm, regid);
registerPushToken.execute();
}
(...)
}
#Override
public void onTaskCompleted(String responseRegid) {
try {
// load authToken from Server: JsonObjectRequest
builderOnFailureDialog = new MaterialDialog.Builder(activity)
.title(getResources().getString(R.string.registrierung_dialog_registrieren_failure_retry_title))
.content(onFailureDialogContent)
.positiveText(getResources().getString(R.string.registrierung_dialog_registrieren_failure_retry_positive_text))
.negativeText(getResources().getString(R.string.registrierung_dialog_registrieren_failure_retry_negative_text))
.onNegative(new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
activity.finish();
}
});
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
try {
onFailureDialog.dismiss();
onSuccessDialog.dismiss();
} catch (Exception e) {
Log.e("Activity.onDestroy()", e.getMessage());
}
}
}
Or is the reason for the problem the async task running in background?
call finish() inside runOnUiThread().
i.e.
replace
finish();
with
runOnUiThread(new Runnable() {
public void run() {
finish()
}
});
I'm making a simple app client-server in java, i want my phone to receive and send messages to my pc, i'm on same LAN and my pc's ip is 192.168.1.8, my serverSocket is running on port 7777.
for some reason my client android cant connect i think it is because i created a socket in a thread, i have read that i should use AsyncTask or Handle, i tried with that too but i get an exception too.
Class server:
public class MyServer implements Runnable{
private ServerSocket server;
private ObjectInputStream in;
private ObjectOutputStream out;
private Socket clientedConnected;
public ExampleServerZNuC(){
try {
server= new ServerSocket(7777);
System.out.println("server opened on port 7777");
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendMessage(String message){
try {
out.writeObject(message);
out.flush();
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void sendNotifiy(){
try {
out.writeObject("Send Notify");
out.flush();
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String getMessage(){
return "";
}
public void run(){
System.out.println("method run started");
System.out.println("Waiting for a client to connect");
try {
Socket clientedConnected;
clientedConnected = server.accept();
System.out.println("A client connected : "+clientedConnected.getInetAddress().getHostAddress());
in= new ObjectInputStream(clientedConnected.getInputStream());
out = new ObjectOutputStream(clientedConnected.getOutputStream());
} catch (IOException ex) {
Logger.getLogger(MyServer.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("End of method Run");
} }
this is the output i get when i create run the server:
server opened on port 7777
method run started
Waiting for a client to connect
client android:
class to connect to my server( atm i just want it to receive the message):
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.net.Socket;
import java.net.UnknownHostException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MyConnect implements Runnable{
private Socket myconnect=null ;
private TextView txtMessage;
private ObjectInputStream in;
private ObjectOutputStream out;
public MyConnect( ){
try {
// this is my pc's IP, my phone is connected to same LAN
Log.d("inizializating socket","");
myconnect= new Socket("192.168.1.8",7777);
in = new ObjectInputStream(myconnect.getInputStream());
out = new ObjectOutputStream(myconnect.getOutputStream());
} catch (UnknownHostException e) {
Log.d("My Error connecting",e.getMessage());
} catch (IOException e) {
Log.d("My Error connecting",e.getMessage());
}
}
#Override
public void run() {
try {
String message = (String)in.readObject();
Log.d("messaged recived",message);
} catch (OptionalDataException e) {
Log.d("My Error connecting",e.getMessage());
} catch (ClassNotFoundException e) {
Log.d("Error My ClassNotFoundException",e.getMessage());
} catch (IOException e) {
Log.d("Error My IOEXCEPTION",e.getMessage());
}
}
}
this is the error that i get when i click on a button that should create the socket:
on create i use connect= new MyConnect();
and on onclick event i use:
#Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btnExample:
new Thread(connect).start();
break;
}
}
error message :
05-29 19:02:05.905: E/AndroidRuntime(6520): FATAL EXCEPTION: main
05-29 19:02:05.905: E/AndroidRuntime(6520): android.os.NetworkOnMainThreadException
05-29 19:02:05.905: E/AndroidRuntime(6520): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
05-29 19:02:05.905: E/AndroidRuntime(6520): at libcore.io.IoBridge.connect(IoBridge.java:112)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.Socket.startupSocket(Socket.java:566)
05-29 19:02:05.905: E/AndroidRuntime(6520): at java.net.Socket.tryAllAddresses(Socket.java:127)
EDIT:
class MySyncTask extends AsyncTask<Integer, Integer, String>{
String advice;
#Override
protected String doInBackground(Integer... params) {
try {
s = new Socket("192.168.1.8",7777);
Log.d("socket connected","");
ObjectInputStream streamReader = new ObjectInputStream(s.getInputStream());
advice = (String)streamReader.readObject();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
protected void onPostExecute(String result) {
txtMessage.setText("you got a message: " + advice);
}
protected void onPreExecute() {
Log.d("my started","start");
}
}
and i used
MySyncTask asyncTask=new MySyncTask ();
asyncTask.execute();
on onCreate() method but for some reason it is not connecting to my server
LogCat with AsyncTask:
05-29 19:46:21.900: D/my started(26169): start
05-29 19:46:22.020: D/libEGL(26169): loaded /system/lib/egl/l ibEGL_mali.so
05-29 19:46:22.030: D/libEGL(26169): loaded /system/lib/egl/libGLESv1_CM_mali.so
05-29 19:46:22.040: D/libEGL(26169): loaded /system/lib/egl/libGLESv2_mali.so
05-29 19:46:22.080: D/OpenGLRenderer(26169): Enabling debug mode 0
EDIT PROBLEM SOLVED
after searching on internet why socket was not connecting i found someone who had a similar problem and i found the answer here Android Socket not being instantiated
i had to initializate the socket first and then use connect
This is happening because you are trying to perform a networking operation on the main thread. This is bad design, you do not want to lock up the user interface while you run a process that can take long time to execute.
Put your network method in an AsyncTask or Service.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Like Eduardo points out,
NetworkOnMainThreadException
The exception that is thrown when an application attempts to perform a
networking operation on its main thread.
Use Asynctask for your connection
Be sure to have
<uses-permission android:name="android.permission.INTERNET" />
into your AndroidManifest.xml
Have you set the proper permissions in the manifest? If yes, is the phone on the same network as your PC (if they are on same wifi network is good)? Try running through debugger and putting a break point.
Here is a nice tutorial that explains client/server communication in android.
http://examples.javacodegeeks.com/android/core/socket-core/android-socket-example/
Good luck
-Raghu
I'm having trouble with the case where a SocketChannel.connect times out. The code bellow works fine in my old Android 2.3 phone and my old Android 3.2 tablet but crashes in Android 4.2.2:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = (TextView) findViewById(R.id.tvResult);
btnTest = (Button) this.findViewById(R.id.btnTest);
btnTest.setOnClickListener(doTest);
}
protected View.OnClickListener doTest = new View.OnClickListener() {
#Override
public void onClick(View v) {
new AsyncTest().execute();
}
};
private class AsyncTest extends AsyncTask {
private String result = "";
#Override
protected Void doInBackground(Void... params) {
InetSocketAddress addr = new InetSocketAddress("192.168.0.13", 4040);
boolean bConnect = false;
try {
SocketChannel clntChan = SocketChannel.open();
bConnect = clntChan.connect(addr);
if (bConnect) {
clntChan.close();
result = "Connected";
} else {
result = "Did not connected";
}
} catch (Exception e) {
Log.e(TAG, "Exception " + e.getMessage());
result = "Exception " + e.getMessage();
}
return null;
}
#Override
protected void onPostExecute(Void ret) {
tvResult.setText (result);
}
}
I am testing the case where there is no one is listening on port 4040 at 192.168.0.13. In Android 2.3 the try/catch will catch a "Connection timeout" exception (as expected). In Android 4.x I get the following:
FATAL EXCEPTION: AsyncTask #1
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:299)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
at java.util.concurrent.FutureTask.run(FutureTask.java:239)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
at java.lang.Thread.run(Thread.java:838)
Caused by: java.lang.AssertionError: java.net.SocketTimeoutException: failed to connect to /192.168.0.13 (port 4040) after 90000ms
at libcore.io.IoBridge.connect(IoBridge.java:102)
at java.nio.SocketChannelImpl.connect(SocketChannelImpl.java:177)
at br.com.dqsoft.testeconnect.MainActivity$AsyncTest.doInBackground(MainActivity.java:63)
at br.com.dqsoft.testeconnect.MainActivity$AsyncTest.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:287)
at java.util.concurrent.FutureTask.run(FutureTask.java:234)
... 4 more
Caused by: java.net.SocketTimeoutException: failed to connect to /192.168.0.13 (port 4040) after 90000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java:176)
at libcore.io.IoBridge.connect(IoBridge.java:112)
at libcore.io.IoBridge.connect(IoBridge.java:100)
... 9 more
A could not find a way to catch this exception, the app is closed by the OS. While a timeout is not a normal condition, I should be able to detect that and present an error message to the user instead of just crashing.
The case where the connect succeeds works fine in all the devices.
Edit: The initial paragraph erroneously mentioned Android 2.4 instead of 4.2.2.
Edit: Simplified the code as suggest by Jarred and added additional information.
Update: Tested on a Android 4.4.4 device and it worked. I will close this as a bug of Android 4.2.2 (maybe on this specific device).
Remove most of this:
You are starting a Thread from a Thread form another Thread. Just start a single Thread from your Main Thread, using your AsyncTask.
protected View.OnClickListener doTest = new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new threadTest()).start();
}
};
private class threadTest implements Runnable {
#Override
public void run() {
try {
runOnUiThread(new Runnable() {
#Override
public void run() {
new AsyncTest().execute();
}
});
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
}
Change it to:
protected View.OnClickListener doTest = new View.OnClickListener() {
#Override
public void onClick(View v) {
new AsyncTest().execute();
}
};
For the Exception and Timeout:
IOException is the parent class of SocketTimeoutException, so your AsyncTask code should work. When in doubt, you can catch everything by using Exception.
Other things to check:
Can you ping 192.168.0.13?
How do you know that port is open? Try telnet or netcat.
Do you have a service running and configured correctly on the port?
Do you have the correct Android Permissions?
public static MediaPlayer mp=null;
public static void playGeneric(int name, final ImageButton button,final ImageButton pervious,Context context) {
button.setEnabled(false);
button.setClickable(false);
pervious.setEnabled(false);
pervious.setClickable(false);
try{
if(mp != null && mp.isPlaying())
{
mp.stop();
mp.release();
mp = null;
mp=MediaPlayer.create(context, name);
mp.start();
}
else
{
mp = MediaPlayer.create(context, name);
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer arg0) {
//mp.prepare();
mp.start();
}
});
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
System.out.println("Object released");
button.setEnabled(true);
button.setClickable(true);
pervious.setEnabled(true);
pervious.setClickable(true);
}
});
}
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
e.getMessage();
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
e.getMessage();
}
}
give me java.lang.IllegalStateException on mp.isplaying() method.
I want to stop music if it's playing and play another song one after another.
logcat:
10-14 15:12:05.474: E/MediaPlayer(15411): prepareAsync called in state 8
10-14 15:12:05.474: W/System.err(15411): java.lang.IllegalStateException
10-14 15:12:05.474: W/System.err(15411): at android.media.MediaPlayer.prepare(Native Method)
10-14 15:12:05.474: W/System.err(15411): at com.rogerscenter.LearnReadWriteSpell.Utility.Music.playGeneric(Music.java:93)
10-14 15:12:05.474: W/System.err(15411): at com.rogerscenter.LearnReadWriteSpell.LetterCategory.Letter_Lesson1_activity.onCreate(Letter_Lesson1_activity.java:140)
10-14 15:12:05.474: W/System.err(15411): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-14 15:12:05.474: W/System.err(15411): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1586)
10-14 15:12:05.474: W/System.err(15411): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1638)
10-14 15:12:05.474: W/System.err(15411): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
10-14 15:12:05.474: W/System.err(15411): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:928)
10-14 15:12:05.484: W/System.err(15411): at android.os.Handler.dispatchMessage(Handler.java:99)
10-14 15:12:05.484: W/System.err(15411): at android.os.Looper.loop(Looper.java:123)
10-14 15:12:05.484: W/System.err(15411): at android.app.ActivityThread.main(ActivityThread.java:3647)
10-14 15:12:05.484: W/System.err(15411): at java.lang.reflect.Method.invokeNative(Native Method)
10-14 15:12:05.484: W/System.err(15411): at java.lang.reflect.Method.invoke(Method.java:507)
10-14 15:12:05.484: W/System.err(15411): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-14 15:12:05.484: W/System.err(15411): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-14 15:12:05.484: W/System.err(15411): at dalvik.system.NativeStart.main(Native Method)
Try changing mp.release() into reset(). that could help you.
As android docs suggest that if mp is if has not been initialized at that time java.lang.IllegalStateException will be thrown so you have to initilize first or you have to write
check out the docs http://developer.android.com/reference/android/media/MediaPlayer.html#isPlaying()
try like this
mp=MediaPlayer.create(context, name);
try {
if (mp.isPlaying()) {
mp.stop();
mp.release();
mp=MediaPlayer.create(context, name);
}
mp.start();
} catch (Exception e) {
}
Ok i am here with my solution, hope it will help others.
(i) if you are using videoView and mediaPlayer.isPlaying() (isNative) error occurs
on activity stop
Add this onStop() method:
if (videoView != null && videoView.isPlaying()) {
videoView.pause();
videoView.stopPlayback();
}
Note: Don't use mediaPlayer.stop() or mediaPlayer.release() here when you work with videoView, it will throw IllegalException
(ii) If you are using mediaPlayer to play only audio
Add this onStop() method:
try {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
Note: This is only for those who get error when your activity is in stop or in resume state.
This could happen if you are trying to stop audio when the player hasn't started playing yet. Hence the IllegalStateException
See if you can prevent that. You can also putting a try catch around the isPlaying()
fun isPlaying(): Boolean {
return try {
mediaPlayer?.isPlaying == true
} catch (illegalStateException: IllegalStateException) {
DebugLog.d(TAG, illegalStateException.message)
DebugLog.d(TAG, illegalStateException.stackTraceToString())
false
}
}
use runOnUiThread for mediaRecorder prepare.
private boolean prepareMediaRecorder() {
mediaRecorder = new MediaRecorder();
runOnUiThread(new Runnable() {
#Override
public void run() {
mediaRecorder.reset();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mediaRecorder.setOutputFile(filePath);
try {
mediaRecorder.prepare();
} catch (IOException e) {
mediaRecorder = null;
return;
}
mediaRecorder.start();
recording = true;
}
});
return true;
}
The Bluetooth device I am trying to connect has always the same pincode. This should make it possible to pair the device by setting the pin programmatically.
After trying to search how this could be done, I ended up with the code below:
BluetoothDevice device = getDevice();
//To avoid the popup notification:
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
device.getClass().getMethod("cancelPairingUserInput", boolean.class).invoke(device, true);
byte[] pin = ByteBuffer.allocate(4).putInt(1234).array();
//int pinn = 1234;
//Entering pin programmatically:
Method ms = device.getClass().getMethod("setPin", byte[].class);
//Method ms = device.getClass().getMethod("setPasskey", int.class);
ms.invoke(device, pin);
//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);
cancelPairingUserInput gives me a NoSuchMethodException, which is weird because the method does exist in BluetoothDevice class.
Is looks like Setpin or SetPasskey doesn't do anything. The device just wont pair. It only pairs after manually entering the pin.
So the only line of code that works is:
//Bonding the device:
Method mm = device.getClass().getMethod("createBond", (Class[]) null);
mm.invoke(device, (Object[]) null);
Logcat output:
09-27 12:34:46.408: ERROR/App(11671): cancelPairingUserInput [boolean]
java.lang.NoSuchMethodException: cancelPairingUserInput [boolean]
at java.lang.Class.getConstructorOrMethod(Class.java:460)
at java.lang.Class.getMethod(Class.java:915)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.pair(BluetoothDiscoveryAndPairing.java:97)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing.access$000(BluetoothDiscoveryAndPairing.java:25)
at test.app.bluetooth.model.BluetoothDiscoveryAndPairing$1.onReceive(BluetoothDiscoveryAndPairing.java:79)
at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:756)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4921)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(Native Method)
So what am I doing wrong?
The hidden method cancelPairingUserInput does not exist in your device. Don't use it.
You should register BroadcastReceiver for android.bluetooth.device.action.PAIRING_REQUEST
Call createBond()
Wait for BroadcastReceiver to trigger
In BroadcastReceiver if action is android.bluetooth.device.action.PAIRING_REQUEST
call this method
public void setBluetoothPairingPin(BluetoothDevice device)
{
byte[] pinBytes = convertPinToBytes("0000");
try {
Log.d(TAG, "Try to set the PIN");
Method m = device.getClass().getMethod("setPin", byte[].class);
m.invoke(device, pinBytes);
Log.d(TAG, "Success to add the PIN.");
try {
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
Log.d(TAG, "Success to setPairingConfirmation.");
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
e.printStackTrace();
}
}
It also works on a device with Jelly Bean version (4.1.2) of Android.
this is works for me:
IntentFilter filter2 = new IntentFilter(
"android.bluetooth.device.action.PAIRING_REQUEST");
mActivity.registerReceiver(
pairingRequest, filter2);
private final BroadcastReceiver pairingRequest = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.bluetooth.device.action.PAIRING_REQUEST")) {
mBluetoothDevice = needed;
try {
byte[] pin = (byte[]) BluetoothDevice.class.getMethod("convertPinToBytes", String.class).invoke(BluetoothDevice.class, "1234");
Method m = mBluetoothDevice.getClass().getMethod("setPin", byte[].class);
m.invoke(mBluetoothDevice, pin);
mBluetoothDevice.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(mBluetoothDevice, true);
}
catch(Exception e)
{
e.printStackTrace();
}