I have java.util.concurrent.RejectedExecutionException in this file. As I can see there is no more processes running after onStop called. Not sure where the error comes from. And I'm sure the executor isn't getting more tasks it can handle too.
Please help me to figure out where the error comes from.
public static final String TAG = BroadcastService.class.getSimpleName();
private static final int TIMER_DELAY_SECONDS = 3;
private volatile JmDNS mService = null;
private WifiManager.MulticastLock mMulticastLock = null;
private ScheduledExecutorService mExecutorService = null;
private ScheduledFuture mPublisherFuture = null;
private ScheduledFuture mApiPublisherFuture = null;
private NetworkUtils mNetworkUtils = null;
private Runnable mDelayedKiller = null;
public static Intent getStartIntent(Context context) {
final Intent serviceIntent = new Intent(context, BroadcastService.class);
serviceIntent.setAction(BroadcastService.INTENT_ACTION_BROADCAST_START);
return serviceIntent;
}
public static Intent getStopIntent(Context context) {
final Intent serviceIntent = new Intent(context, BroadcastService.class);
serviceIntent.setAction(BroadcastService.INTENT_ACTION_BROADCAST_STOP);
return serviceIntent;
}
#Override
public void onCreate() {
super.onCreate();
mNetworkUtils = NetworkUtils.getInstance(getApplicationContext());
}
#Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
if (intent == null) {
return START_STICKY;
}
if (intent.getAction() != null) {
switch (intent.getAction()) {
case INTENT_ACTION_BROADCAST_START:
startBroadcast();
break;
case INTENT_ACTION_BROADCAST_STOP:
stopBroadcast();
break;
}
}
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(final Intent intent) {
return null;
}
/**
* Starts broadcast on a background thread
*/
public void startBroadcast() {
if (mDelayedKiller != null) {
NetworkThread.getCommonInstance().removeTask(mDelayedKiller);
mDelayedKiller = null;
}
if (mExecutorService == null || mExecutorService.isShutdown()) {
mExecutorService = Executors.newScheduledThreadPool(2);
}
if (mPublisherFuture != null) {
mPublisherFuture.cancel(true);
}
final BonjourPublisher bonjourPublisher = new BonjourPublisher();
mPublisherFuture = mExecutorService.schedule(bonjourPublisher, 2, TimeUnit.SECONDS);
if (mApiPublisherFuture != null) {
mApiPublisherFuture.cancel(true);
}
final ApiPublisher apiPublisher = new ApiPublisher();
mApiPublisherFuture = mExecutorService.scheduleWithFixedDelay(apiPublisher, 0, 30, TimeUnit.SECONDS);
//inform listeners
EventBus.getDefault().post(new EventServiceBroadcasting(true));
}
public synchronized void stopBroadcast() {
if (mPublisherFuture == null && mApiPublisherFuture == null) {
return;
}
if (mPublisherFuture != null) {
mPublisherFuture.cancel(true);
if (mMulticastLock != null) {
mMulticastLock.release();
mMulticastLock = null;
}
}
if (mApiPublisherFuture != null) {
mApiPublisherFuture.cancel(true);
}
mDelayedKiller = new Runnable() {
#Override
public void run() {
mExecutorService.shutdownNow();
killService();
stopSelf();
}
};
NetworkThread.getCommonInstance().postDelayed(mDelayedKiller, 1000 * 20); //kill the service after 20 seconds
//inform listeners
EventBus.getDefault().post(new EventServiceBroadcasting(false));
}
#Override
public void onDestroy() {
super.onDestroy();
killService();
}
private synchronized void killService() {
if (mService != null) {
try {
mService.unregisterAllServices();
mService.close();
mService = null;
} catch (IOException e) {
e.printStackTrace();
}
} else {
}
}
public static class DiscoverableAssistant {
private DiscoverableAssistant() {
}
public static boolean isDiscoverable(Context context) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(PREF_DEVICE_DISCOVERABLE, true); //true by default
}
public static void setDiscoverable(Context context, boolean discoverable) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
prefs.edit().putBoolean(PREF_DEVICE_DISCOVERABLE, discoverable).apply();
}
}
private class BonjourPublisher implements Runnable {
#Override
public void run() {
final String serviceName = mNetworkUtils.getDeviceName(BroadcastService.this);
final String serviceType = getString(R.string.multi_dns_network_name);
final Map<String, String> properties = new HashMap<>();
properties.put(DeviceViewActivity.DEVICE_PROPERTY_DEVICE_TYPE, "Android");
properties.put(DeviceViewActivity.DEVICE_PROPERTY_FILE_SERVER_PORT,
String.valueOf(mNetworkUtils.getAssignedPort()));
if (DiscoverableAssistant.isDiscoverable(BroadcastService.this)) {
properties.put(DeviceViewActivity.DEVICE_PROPERTY_DISCOVERABLE, "true");
} else {
properties.put(DeviceViewActivity.DEVICE_PROPERTY_DISCOVERABLE, "false");
}
//acquire wifi multicast lock
if (mMulticastLock == null) {
final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
mMulticastLock.setReferenceCounted(true);
mMulticastLock.acquire();
}
try {
if (mService == null) {
mService = JmDNS.create(mNetworkUtils.getMyInet4Address(),
NetworkUtils.getHostName(mNetworkUtils.getDeviceName(BroadcastService.this)));
}
final ServiceInfo info = ServiceInfo.create(serviceType, serviceName, mNetworkUtils.getAssignedPort(), 0, 0, true, properties);
while (mService != null) {
mService.registerService(info);
Thread.sleep(TIMER_DELAY_SECONDS * 1000);
mService.unregisterAllServices();
Thread.sleep(1000);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
} catch (Exception e) {
}
}
}
private class ApiPublisher implements Runnable {
private APo api = null;
private SimplifiedDeviceInfo mDeviceInfo = null;
public ApiPublisher() {
api = Utils.getRetrofitInstance(BroadcastService.this, null)
.create(api.class);
}
#Override
public void run() {
try {
if (mDeviceInfo == null) {
mDeviceInfo = new SimplifiedDeviceInfo(mNetworkUtils.getDeviceName(BroadcastService.this),
mNetworkUtils.getMyInet4Address().getHostAddress(), mNetworkUtils.getAssignedPort(),
NetworkUtils.getDeviceType(), BroadcastService.DiscoverableAssistant.isDiscoverable(BroadcastService.this));
}
Call<JsonElement> call = api.broadcastDevice(mDeviceInfo);
call.execute();
} catch (Exception e) {
}
}
}
The a RejectedExecutionException is thrown when you attempt to submit a task to an executor, and it is refuses it. In this case, there is a clue in the exception message:
java.util.concurrent.ScheduledThreadPoolExecutor#42209b70[
Shutting down, pool size = 2, active threads = 2,
queued tasks = 0, completed tasks = 248]
This is telling me that you are attempting to submit a task to an Executor that is being shut down.
Now I can't pretend that I understand what your code is actually doing, but I can see that it is using postThread to schedule a Runnable that shuts down the executor. My guess is that the app has done that ... and then it is somehow trying to submit another task.
In reading your code I spotted a couple of places where you catch and then squash Exception. That is a really bad idea. I wouldn't be surprised if that is why you are having trouble debugging your code.
Related
This is in relation to the question How to run a background task in android when the app is killed which I posted a few days ago.
After reading some blogs (e.g this) and code (of telephony) I have done some coding. My requirement is to show the user some sort of notification when a call is received, even when my app is not running (much like the Truecaller app in android). I am posting the code below.
callback_dispatcher.dart
const String HANDLE_INCOMING_CALL_BG = "handleIncomingCallBg";
const String INCOMING_CALL_BG_INITIALIZED = "incomingCallBgInitialized";
const String INCOMING_CALL_BG_INIT_SERVICE = "incomingCallBgInitService";
const String backgroundChannelId = "background_channel";
const String foregroundChannelId = "foreground_channel";
void callback_dispatcher() {
const MethodChannel _backgroundChannel = MethodChannel(backgroundChannelId);
WidgetsFlutterBinding.ensureInitialized();
_backgroundChannel.setMethodCallHandler((MethodCall call) =>
methodCallHandler(call));
_backgroundChannel.invokeMethod<void>(INCOMING_CALL_BG_INITIALIZED);
}
Future<dynamic> methodCallHandler(MethodCall call) async {
if(call.method == HANDLE_INCOMING_CALL_BG) {
final CallbackHandle _handle =
CallbackHandle.fromRawHandle(call.arguments['handle']);
final Function _handlerFunc = PluginUtilities.getCallbackFromHandle(_handle)!;
try {
await _handlerFunc(call.arguments['message']);
} catch(e) {
print('Unable to handle incoming call in background');
print(e);
}
}
return Future<void>.value();
}
void handleBgMsg(String msg) {
debugPrint("[handleBgMsg] incoming call number : " + msg);
// notification to user
}
background_incoming_call.dart
typedef BgMessageHandler(String msg);
class BackgroundIncomingCall {
MethodChannel? foregroundChannel;
Future<void> initialize(BgMessageHandler onBgMessage) async {
foregroundChannel = const MethodChannel(foregroundChannelId);
final CallbackHandle? bgSetupHandle =
PluginUtilities.getCallbackHandle(callback_dispatcher);
final CallbackHandle? bgMsgHandle =
PluginUtilities.getCallbackHandle(onBgMessage);
await foregroundChannel?.invokeMethod<bool>(
INCOMING_CALL_BG_INIT_SERVICE,
<String, dynamic> {
'bgSetupHandle': bgSetupHandle?.toRawHandle(),
'bgMsgHandle': bgMsgHandle?.toRawHandle()
}
);
}
}
In main.dart I am initializing BackgroundIncomingCall().initialize(handleBgMsg);.
On the Android part I have created a BroadcastReceiver as follows (the code mostly from the aforementioned Telephony package).
public class CallEventReceiver extends BroadcastReceiver implements
MethodChannel.MethodCallHandler {
private static final String TAG = "[TEST]";
private static final int NUMBER_LEN = 10;
public static String INCOMING_CALL_BG_INITIALIZED = "incomingCallBgInitialized";
public static String INCOMING_CALL_BG_INIT_SERVICE = "incomingCallBgInitService";
public static String SETUP_HANDLE = "bgSetupHandle";
public static String MESSAGE_HANDLE = "bgMsgHandle";
public static String BG_INCOMING_CALL_CHANNEL_ID = "background_channel";
public static String FG_INCOMING_CALL_CHANNEL_ID = "foreground_channel";
public static String HANDLE_INCOMING_CALL_BG = "handleIncomingCallBg";
public static String SHARED_PREF_NAME = "incomingCallSharedPrefBg";
public static String SHARED_PREF_BG_INCOMING_CALL_HANDLE = "incomingCallSharedPrefBgHandle";
public static String SHARED_PREFS_BACKGROUND_SETUP_HANDLE = "backgroundSetupHandle";
private Activity activity = null;
/* for background isolate*/
private Context appContext = null;
private AtomicBoolean isIsolateRunning = new AtomicBoolean(false);
private List<String> bgIncomingCallQueue = Collections.synchronizedList(new ArrayList<String>());
private MethodChannel bgIncomingCallChannel = null;;
private MethodChannel fgIncomingCallChannel = null;;
private FlutterLoader flutterLoader = null;
private FlutterEngine bgFlutterEngine = null;
private Long bgIncomingCallHandle = null;
/* END */
public CallEventReceiver() {}
public CallEventReceiver(Activity activity) {
super();
this.activity = activity;
}
#Override
public void onMethodCall(#NonNull MethodCall call, #NonNull MethodChannel.Result result) {
if(call.method.equals(INCOMING_CALL_BG_INITIALIZED)) {
if(appContext != null) {
onChannelInitialized(appContext);
} else {
throw new RuntimeException("Application context is not set");
}
} else if(call.method.equals(INCOMING_CALL_BG_INIT_SERVICE)) {
if(appContext != null) {
if(call.hasArgument(SETUP_HANDLE) && call.hasArgument(MESSAGE_HANDLE)) {
Long setupHandle = call.<Long>argument(SETUP_HANDLE);
Long msgHandle = call.<Long>argument(MESSAGE_HANDLE);
if (setupHandle == null || msgHandle == null) {
result.error("ILLEGAL_ARGS", "Setup handle or message handle is missing", null);
return;
}
setBgSetupHandle(appContext, setupHandle);
setBgMessageHandle(appContext, msgHandle);
}
} else {
throw new RuntimeException("Application context is not set");
}
} else {
result.notImplemented();
}
}
#Override
public void onReceive(Context context, Intent intent) {
this.appContext = context;
try {
Log.i(TAG, "[CallEventHandler] Receiver start");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
if(incomingNumber != null) {
Log.i(TAG, "[CallEventHandler] Incoming number : " + incomingNumber);
if(incomingNumber.length() > NUMBER_LEN) {
incomingNumber = incomingNumber.substring(incomingNumber.length() - NUMBER_LEN, incomingNumber.length());
Log.i(TAG, "[CallEventHandler] Incoming number after : " + incomingNumber);
processIncomingCall(context, incomingNumber);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void setBgMessageHandle(Context ctx, Long handle) {
bgIncomingCallHandle = handle;
SharedPreferences pref = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
pref.edit().putLong(SHARED_PREF_BG_INCOMING_CALL_HANDLE, handle).apply();
}
public void setBgSetupHandle(Context ctx, Long setupBgHandle) {
SharedPreferences pref = ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
pref.edit().putLong(SHARED_PREFS_BACKGROUND_SETUP_HANDLE, setupBgHandle).apply();
}
private void processIncomingCall(Context ctx, String incomingNumber) {
boolean isForeground = isAppForeground(ctx);
Log.i(TAG, "[processIncomingCall] is app in foreground : " + isForeground);
if (isForeground) {
processIncomingCallInForeground(incomingNumber);
} else {
processIncomingCallInBackground(ctx, incomingNumber);
}
}
private void processIncomingCallInBackground(Context ctx, String incomingNumber) {
if(!isIsolateRunning.get()) {
init(ctx);
SharedPreferences sharedPref = ctx.getSharedPreferences(SHARED_PREF_NAME,
Context.MODE_PRIVATE);
Long bgCallbackHandle = sharedPref.getLong(SHARED_PREFS_BACKGROUND_SETUP_HANDLE, 0);
startBackgroundIsolate(ctx, bgCallbackHandle);
bgIncomingCallQueue.add(incomingNumber);
} else {
executeDartCallbackInBgIsolate(ctx, incomingNumber);
}
}
private void processIncomingCallInForeground(String incomingNumber) {
Log.i(TAG, "[processIncomingCallInFg] incoming number : " + incomingNumber);
if(activity != null) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
if(eventSink != null) {
eventSink.success(incomingNumber);
}
}
});
}
}
private void onChannelInitialized(Context ctx) {
isIsolateRunning.set(true);
synchronized(bgIncomingCallQueue) {
Iterator<String> it = bgIncomingCallQueue.iterator();
while(it.hasNext()) {
executeDartCallbackInBgIsolate(ctx, it.next());
}
bgIncomingCallQueue.clear();
}
}
private void init(Context ctx) {
FlutterInjector flutterInjector = FlutterInjector.instance();
flutterLoader = flutterInjector.flutterLoader();
flutterLoader.startInitialization(ctx);
}
private void executeDartCallbackInBgIsolate(Context ctx, String incomingNumber) {
if(bgIncomingCallChannel == null) {
throw new RuntimeException("background channel is not initialized");
}
if(bgIncomingCallHandle == null) {
bgIncomingCallHandle = getBgMessageHandle(ctx);
}
HashMap<String, Object> args = new HashMap<String, Object>();
args.put("handle", bgIncomingCallHandle);
args.put("message", incomingNumber);
bgIncomingCallChannel.invokeMethod(HANDLE_INCOMING_CALL_BG, args);
}
private Long getBgMessageHandle(Context ctx) {
return ctx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
.getLong(SHARED_PREF_BG_INCOMING_CALL_HANDLE, 0);
}
private void startBackgroundIsolate(Context ctx, Long callbackHandle) {
String appBundlePath = flutterLoader.findAppBundlePath();
FlutterCallbackInformation cbInfo = FlutterCallbackInformation.
lookupCallbackInformation(callbackHandle);
DartExecutor.DartCallback dartEntryPoint =
new DartExecutor.DartCallback(ctx.getAssets(), appBundlePath, cbInfo);
bgFlutterEngine = new FlutterEngine(ctx, flutterLoader, new FlutterJNI());
bgFlutterEngine.getDartExecutor().executeDartCallback(dartEntryPoint);
bgIncomingCallChannel = new MethodChannel(bgFlutterEngine.getDartExecutor(),
BG_INCOMING_CALL_CHANNEL_ID);
bgIncomingCallChannel.setMethodCallHandler(this);
}
private boolean isAppForeground(Context ctx) {
KeyguardManager keyGuardManager = (KeyguardManager) ctx.
getSystemService(Context.KEYGUARD_SERVICE);
if(keyGuardManager.isKeyguardLocked()) {
return false;
}
int pid = Process.myPid();
ActivityManager activityManager = (ActivityManager) ctx.
getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> list =
activityManager.getRunningAppProcesses();
for(ActivityManager.RunningAppProcessInfo proc : list) {
if(pid == proc.pid) {
return proc.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
}
}
return false;
}
}
In my AndroidManifest.xml I am registering the broadcast receiver
<receiver android:name="org.cdot.diu.handler.CallEventReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
Now If I run my app and minimize it, the handleBgMsg is called successfully. Since no print or debug message is shown in terminal when I kill the app, I am sending an SMS to me using Telephony package, which is sent successfully when the app is minimized. But it does not work if I kill the application, no SMS is sent. I am not sure what I am doing wrong here. My guess is that the Broadcast Receiver is killed when the app is killed. However, in the telephony package there is nothing to indicate that special care is done to keep the receiver alive when the app is killed.
I keep getting an an error when trying to call WowZa GoCoder SDK's PlayerActivity and I am unable to understand the cause. The error appears when mStreamPlayerView.play(mStreamPlayerConfig, statusCallback) is called. Would really appreciate help on where i am going wrong
vodFragment.java
public class vodFragment extends Fragment {
private int mColumnCount = 1;
ListView videoView;
ArrayList <Vidoes> videoList;
private static String value;
String videoName;
String url = "http://192.168.43.149/twende/channelVOD.php";
public vodFragment() {
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (getActivity().getActionBar() != null) {
getActivity().getActionBar().setTitle(value);
}
View view = inflater.inflate(R.layout.fragment_vod_list, container, false);
videoView = (ListView) view.findViewById(R.id.listView);
videoList = new ArrayList<Vidoes>();
JSONObject channelInfo = new JSONObject();
try {
channelInfo.put("channelName", value);
channelInfo.put("channelOwner", "dan");
postJSONObject(url,channelInfo);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return view;
}
public static void setChannel(String channel){
value = channel;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
}
public void postJSONObject(final String myurl, final JSONObject parameters) {
class postJSONObject extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
loadIntoVodView(s);
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected String doInBackground(Void... voids) {
HttpURLConnection conn = null;
try {
StringBuffer response = null;
URL url = new URL(myurl);
conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000);
conn.setConnectTimeout(15000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
OutputStream out = new BufferedOutputStream(conn.getOutputStream());
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
writer.write(parameters.toString());
writer.close();
out.close();
int responseCode = conn.getResponseCode();
System.out.println("responseCode" + responseCode);
switch (responseCode) {
case 200:
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (conn != null) {
try {
conn.disconnect();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
return null;
}
}
postJSONObject postJSONObject = new postJSONObject();
postJSONObject.execute();
}
private void loadIntoVodView(String json) throws JSONException {
JSONArray jsonArray = new JSONArray(json);
final String[] videos = new String[jsonArray.length()];
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
videos[i] = removeExtension(obj.getString("title"));
Vidoes vidoe = new Vidoes();
vidoe.setTitle(videos[i]);
videoList.add(vidoe);
}
VideoListAdapter adapter = new VideoListAdapter(getActivity(), R.layout.vodparsedata, videoList);
videoView.setAdapter(adapter);
videoView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
videoName = Arrays.asList(videos).get(position);
Intent intent = new Intent(getActivity(), PlayerActivity.class);
String message = videoName+".mp4";
intent.putExtra("videoName", message);
startActivity(intent);
System.out.println("arr: " + Arrays.asList(videos).get(position));
}
});
}
public static String removeExtension(String fileName) {
if (fileName.indexOf(".") > 0) {
return fileName.substring(0, fileName.lastIndexOf("."));
} else {
return fileName;
}
}
}
PlayerActivity.java
public class PlayerActivity extends GoCoderSDKActivityBase {
final private static String TAG = PlayerActivity.class.getSimpleName();
String videoName;
private WOWZPlayerView mStreamPlayerView = null;
private WOWZPlayerConfig mStreamPlayerConfig = new WOWZPlayerConfig();
private MultiStateButton mBtnPlayStream = null;
private MultiStateButton mBtnSettings = null;
private MultiStateButton mBtnMic = null;
private MultiStateButton mBtnScale = null;
private SeekBar mSeekVolume = null;
private ProgressDialog mBufferingDialog = null;
private StatusView mStatusView = null;
private TextView mHelp = null;
private TimerView mTimerView = null;
private ImageButton mStreamMetadata = null;
private boolean mUseHLSPlayback = false;
private WOWZPlayerView.PacketThresholdChangeListener packetChangeListener = null;
private VolumeChangeObserver mVolumeSettingChangeObserver = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stream_player);
mRequiredPermissions = new String[]{};
if (savedInstanceState == null) {
Bundle extras = getIntent().getExtras();
if(extras == null) {
videoName= null;
} else {
videoName= extras.getString("videoName");
}
} else {
videoName= (String) savedInstanceState.getSerializable("videoName");
}
System.out.print(videoName);
mStreamPlayerConfig.setIsPlayback(true);
mStreamPlayerConfig.setHostAddress("192.168.43.149");
mStreamPlayerConfig.setApplicationName("Dark Souls 2 Channel");
mStreamPlayerConfig.setStreamName(videoName);
mStreamPlayerConfig.setPortNumber(1935);
mStreamPlayerView = (WOWZPlayerView) findViewById(R.id.vwStreamPlayer);
mBtnPlayStream = (MultiStateButton) findViewById(R.id.ic_play_stream);
mBtnSettings = (MultiStateButton) findViewById(R.id.ic_settings);
mBtnMic = (MultiStateButton) findViewById(R.id.ic_mic);
mBtnScale = (MultiStateButton) findViewById(R.id.ic_scale);
mTimerView = (TimerView) findViewById(R.id.txtTimer);
mStatusView = (StatusView) findViewById(R.id.statusView);
mStreamMetadata = (ImageButton) findViewById(R.id.imgBtnStreamInfo);
mHelp = (TextView) findViewById(R.id.streamPlayerHelp);
mSeekVolume = (SeekBar) findViewById(R.id.sb_volume);
WOWZStatusCallback statusCallback = new StatusCallback();
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
mTimerView.setVisibility(View.GONE);
mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);
if (sGoCoderSDK != null) {
/*
Packet change listener setup
*/
final PlayerActivity activity = this;
packetChangeListener = new WOWZPlayerView.PacketThresholdChangeListener() {
#Override
public void packetsBelowMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have fallen below threshold "+packetCount+"... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have fallen below threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void packetsAboveMinimumThreshold(int packetCount) {
WOWZLog.debug("Packets have risen above threshold "+packetCount+" ... ");
activity.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(activity, "Packets have risen above threshold ... ", Toast.LENGTH_SHORT).show();
}
});
}
};
mStreamPlayerView.setShowAllNotificationsWhenBelowThreshold(false);
mStreamPlayerView.setMinimumPacketThreshold(20);
mStreamPlayerView.registerPacketThresholdListener(packetChangeListener);
///// End packet change notification listener
mTimerView.setTimerProvider(new TimerView.TimerProvider() {
#Override
public long getTimecode() {
return mStreamPlayerView.getCurrentTime();
}
#Override
public long getDuration() {
return mStreamPlayerView.getDuration();
}
});
mSeekVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(progress);
}
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
// listen for volume changes from device buttons, etc.
mVolumeSettingChangeObserver = new VolumeChangeObserver(this, new Handler());
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mVolumeSettingChangeObserver);
mVolumeSettingChangeObserver.setVolumeChangeListener(new VolumeChangeObserver.VolumeChangeListener() {
#Override
public void onVolumeChanged(int previousLevel, int currentLevel) {
if (mSeekVolume != null)
mSeekVolume.setProgress(currentLevel);
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.setVolume(currentLevel);
}
}
});
mBtnScale.setState(mStreamPlayerView.getScaleMode() == WOWZMediaConfig.FILL_VIEW);
// The streaming player configuration properties
mStreamPlayerConfig = new WOWZPlayerConfig();
mBufferingDialog = new ProgressDialog(this);
mBufferingDialog.setTitle(R.string.status_buffering);
mBufferingDialog.setMessage(getResources().getString(R.string.msg_please_wait));
mBufferingDialog.setButton(DialogInterface.BUTTON_NEGATIVE, getResources().getString(R.string.button_cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
cancelBuffering(dialogInterface);
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onMetaData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
String meta = "";
if(eventParams!=null)
meta = eventParams.toString();
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+meta);
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onStatus", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> eventName "+eventName+" = "+eventParams.toString());
return null;
}
});
// testing player data event handler.
mStreamPlayerView.registerDataEventListener("onTextData", new WOWZDataEvent.EventListener(){
#Override
public WOWZDataMap onWZDataEvent(String eventName, WOWZDataMap eventParams) {
if(eventParams!=null)
WOWZLog.debug("onWZDataEvent -> "+eventName+" = "+eventParams.get("text"));
return null;
}
});
} else {
mHelp.setVisibility(View.GONE);
mStatusView.setErrorMessage(WowzaGoCoder.getLastError().getErrorDescription());
}
}
#Override
protected void onDestroy() {
if (mVolumeSettingChangeObserver != null)
getApplicationContext().getContentResolver().unregisterContentObserver(mVolumeSettingChangeObserver);
super.onDestroy();
}
/**
* Android Activity class methods
*/
#Override
protected void onResume() {
super.onResume();
syncUIControlState();
}
#Override
protected void onPause() {
if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
// Wait for the streaming player to disconnect and shutdown...
mStreamPlayerView.getCurrentStatus().waitForState(WOWZState.IDLE);
}
super.onPause();
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager
= (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
public boolean isPlayerConfigReady()
{
return false;
}
/*
Click handler for network pausing
*/
public void onPauseNetwork(View v)
{
Button btn = (Button)findViewById(R.id.pause_network);
if(btn.getText().toString().trim().equalsIgnoreCase("pause network")) {
WOWZLog.info("Pausing network...");
btn.setText("Unpause Network");
mStreamPlayerView.pauseNetworkStack();
}
else{
WOWZLog.info("Unpausing network... btn.getText(): "+btn.getText());
btn.setText("Pause Network");
mStreamPlayerView.unpauseNetworkStack();
}
}
/**
* Click handler for the playback button
*/
public void onTogglePlayStream(View v) {
if (mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop();
} else if (mStreamPlayerView.isReadyToPlay()) {
if(!this.isNetworkAvailable()){
displayErrorDialog("No internet connection, please try again later.");
return;
}
// if(!this.isPlayerConfigReady()){
// displayErrorDialog("Please be sure to include a host, stream, and application to playback a stream.");
// return;
// }
mHelp.setVisibility(View.GONE);
WOWZStreamingError configValidationError = mStreamPlayerConfig.validateForPlayback();
if (configValidationError != null) {
mStatusView.setErrorMessage(configValidationError.getErrorDescription());
} else {
// Set the detail level for network logging output
mStreamPlayerView.setLogLevel(mWZNetworkLogLevel);
// Set the player's pre-buffer duration as stored in the app prefs
float preBufferDuration = GoCoderSDKPrefs.getPreBufferDuration(PreferenceManager.getDefaultSharedPreferences(this));
mStreamPlayerConfig.setPreRollBufferDuration(preBufferDuration);
// Start playback of the live stream
mStreamPlayerView.play(mStreamPlayerConfig, this);
}
}
}
/**
* WOWZStatusCallback interface methods
*/
#Override
public synchronized void onWZStatus(WOWZStatus status) {
final WOWZStatus playerStatus = new WOWZStatus(status);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
WOWZStatus status = new WOWZStatus(playerStatus.getState());
switch(playerStatus.getState()) {
case WOWZPlayerView.STATE_PLAYING:
// Keep the screen on while we are playing back the stream
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (mStreamPlayerConfig.getPreRollBufferDuration() == 0f) {
mTimerView.startTimer();
}
// Since we have successfully opened up the server connection, store the connection info for auto complete
GoCoderSDKPrefs.storeHostConfig(PreferenceManager.getDefaultSharedPreferences(PlayerActivity.this), mStreamPlayerConfig);
// Log the stream metadata
WOWZLog.debug(TAG, "Stream metadata:\n" + mStreamPlayerView.getMetadata());
break;
case WOWZPlayerView.STATE_READY_TO_PLAY:
// Clear the "keep screen on" flag
WOWZLog.debug(TAG, "STATE_READY_TO_PLAY player activity status!");
if(playerStatus.getLastError()!=null)
displayErrorDialog(playerStatus.getLastError());
playerStatus.clearLastError();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
mTimerView.stopTimer();
break;
case WOWZPlayerView.STATE_PREBUFFERING_STARTED:
WOWZLog.debug(TAG, "Dialog for buffering should show...");
showBuffering();
break;
case WOWZPlayerView.STATE_PREBUFFERING_ENDED:
WOWZLog.debug(TAG, "Dialog for buffering should stop...");
hideBuffering();
// Make sure player wasn't signaled to shutdown
if (mStreamPlayerView.isPlaying()) {
mTimerView.startTimer();
}
break;
default:
break;
}
syncUIControlState();
}
});
}
#Override
public synchronized void onWZError(final WOWZStatus playerStatus) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
displayErrorDialog(playerStatus.getLastError());
syncUIControlState();
}
});
}
public void onToggleMute(View v) {
mBtnMic.toggleState();
if (mStreamPlayerView != null)
mStreamPlayerView.mute(!mBtnMic.isOn());
mSeekVolume.setEnabled(mBtnMic.isOn());
}
public void onToggleScaleMode(View v) {
int newScaleMode = mStreamPlayerView.getScaleMode() == WOWZMediaConfig.RESIZE_TO_ASPECT ? WOWZMediaConfig.FILL_VIEW : WOWZMediaConfig.RESIZE_TO_ASPECT;
mBtnScale.setState(newScaleMode == WOWZMediaConfig.FILL_VIEW);
mStreamPlayerView.setScaleMode(newScaleMode);
}
public void onStreamMetadata(View v) {
WOWZDataMap streamMetadata = mStreamPlayerView.getMetadata();
WOWZDataMap streamStats = mStreamPlayerView.getStreamStats();
// WOWZDataMap streamConfig = mStreamPlayerView.getStreamConfig().toDataMap();
WOWZDataMap streamConfig = new WOWZDataMap();
WOWZDataMap streamInfo = new WOWZDataMap();
streamInfo.put("- Stream Statistics -", streamStats);
streamInfo.put("- Stream Metadata -", streamMetadata);
//streamInfo.put("- Stream Configuration -", streamConfig);
DataTableFragment dataTableFragment = DataTableFragment.newInstance("Stream Information", streamInfo, false, false);
getFragmentManager().beginTransaction()
.add(android.R.id.content, dataTableFragment)
.addToBackStack("metadata_fragment")
.commit();
}
public void onSettings(View v) {
// Display the prefs fragment
GoCoderSDKPrefs.PrefsFragment prefsFragment = new GoCoderSDKPrefs.PrefsFragment();
prefsFragment.setFixedSource(true);
prefsFragment.setForPlayback(true);
getFragmentManager().beginTransaction()
.replace(android.R.id.content, prefsFragment)
.addToBackStack(null)
.commit();
}
private void syncUIControlState() {
boolean disableControls = (!(mStreamPlayerView.isReadyToPlay() || mStreamPlayerView.isPlaying()) || sGoCoderSDK == null);
if (disableControls) {
mBtnPlayStream.setEnabled(false);
mBtnSettings.setEnabled(false);
mSeekVolume.setEnabled(false);
mBtnScale.setEnabled(false);
mBtnMic.setEnabled(false);
mStreamMetadata.setEnabled(false);
} else {
mBtnPlayStream.setState(mStreamPlayerView.isPlaying());
mBtnPlayStream.setEnabled(true);
if (mStreamPlayerConfig.isAudioEnabled()) {
mBtnMic.setVisibility(View.VISIBLE);
mBtnMic.setEnabled(true);
mSeekVolume.setVisibility(View.VISIBLE);
mSeekVolume.setEnabled(mBtnMic.isOn());
mSeekVolume.setProgress(mStreamPlayerView.getVolume());
} else {
mSeekVolume.setVisibility(View.GONE);
mBtnMic.setVisibility(View.GONE);
}
mBtnScale.setVisibility(View.VISIBLE);
mBtnScale.setVisibility(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled() ? View.VISIBLE : View.GONE);
mBtnScale.setEnabled(mStreamPlayerView.isPlaying() && mStreamPlayerConfig.isVideoEnabled());
mBtnSettings.setEnabled(!mStreamPlayerView.isPlaying());
mBtnSettings.setVisibility(mStreamPlayerView.isPlaying() ? View.GONE : View.VISIBLE);
mStreamMetadata.setEnabled(mStreamPlayerView.isPlaying());
mStreamMetadata.setVisibility(mStreamPlayerView.isPlaying() ? View.VISIBLE : View.GONE);
}
}
private void showBuffering() {
try {
if (mBufferingDialog == null) return;
mBufferingDialog.show();
}
catch(Exception ex){}
}
private void cancelBuffering(DialogInterface dialogInterface) {
if(mStreamPlayerConfig.getHLSBackupURL()!=null || mStreamPlayerConfig.isHLSEnabled()){
mStreamPlayerView.stop(true);
}
else if (mStreamPlayerView != null && mStreamPlayerView.isPlaying()) {
mStreamPlayerView.stop(true);
}
}
private void hideBuffering() {
if (mBufferingDialog.isShowing())
mBufferingDialog.dismiss();
}
#Override
public void syncPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
mWZNetworkLogLevel = Integer.valueOf(prefs.getString("wz_debug_net_log_level", String.valueOf(WOWZLog.LOG_LEVEL_DEBUG)));
mStreamPlayerConfig.setIsPlayback(true);
if (mStreamPlayerConfig != null)
GoCoderSDKPrefs.updateConfigFromPrefsForPlayer(prefs, mStreamPlayerConfig);
}
private class StatusCallback implements WOWZStatusCallback {
#Override
public void onWZStatus(WOWZStatus wzStatus) {
}
#Override
public void onWZError(WOWZStatus wzStatus) {
}
}
}
The error I get is;
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.wowza.gocoder.sdk.sampleapp/com.wowza.gocoder.sdk.sampleapp.PlayerActivity}: java.lang.RuntimeException: Invalid surface: null
You start the stream in onCreate. At this time the Surface used by WOWZPlayerView is not ready yet and the app crashes with the 'Invalid surface' error.
If you look at the sample test in the GoCoder SDK, the playback is started when the user clicks a button. Eg. when the Surface is valid.
Create a button and move your 'mStreamPlayerView.play(mStreamPlayerConfig, statusCallback);' to the button.onClick.
Or ... use any GoCoder SDK v1.7 and more recent.
Please, let me know if I can help any further.
Thanks
So I am running into a problem with a function I made to slowly change the value of a monitored variable over time that is causing all the java logic to lock up. It doesn't seem to be producing an error or make the application crash so it must be getting stuck in the while loop or something but the logging isn't firing while it is locked so I am just very confused. If anyone can help me figure out how to diagnose what is causing the freezing that would be very much appreciated
EDIT: Turns out the problem was updating the UI from another thread, I manged to get it to crash and got the error and used a CountDownTimer instead of the background thread and now it is working fine. For those curious checkout my GitHub for this project.
Function in question:
public static void changeOverTime(final MonitoredVariable<Integer> tVar, final int tTo, final long tTime, final long tUpdateFreq) {
if (tTime < tUpdateFreq) { Log.e(TAG, "Time must be greater then update freq."); }
if (tVar == null) { Log.e(TAG, "Container cannot be null."); }
else {
final Thread tBackgroundThread = new Thread(new Runnable() {
#Override
public void run() {
float tSteps = tTime / tUpdateFreq; // 2000/100 = 20
float tInterval = (tTo - tVar.get()) / tSteps; // 67-175 = -108/20 = -5.4
float tVal = tVar.get(); //175
while (Math.round(tVal) != tTo) { //67(After 20 Times) != 67 -> FALSE
Debug.Log(TAG, "EQ: " + Math.round(tVal) + "?=" + tTo);
tVal += tInterval; // -5.4 * 20(Times) = -108+175 = 67
tryToSleep(tUpdateFreq); // 100ms * 20(Times) = 2000ms total
tVar.set(Math.round(tVal));
}
}
});
tBackgroundThread.start();
}
}
Supporting Function:
private static void tryToSleep(long tTime) {
try { sleep(tTime); }
catch (InterruptedException e) { e.printStackTrace(); }
}
Monitored Variable Class:
public class MonitoredVariable<Prototype> {
protected Prototype mData;
protected ChangeListener mListener;
public MonitoredVariable(Prototype tData) {
this(tData, null);
}
public MonitoredVariable(Prototype tData, ChangeListener tListener) {
if (tListener != null) setListener(tListener);
mData = tData;
}
public Prototype get() {
return mData;
}
public void set(Prototype tData) {
if (mData != tData) {
mData = tData;
notifyChange();
}
}
public void setListener(ChangeListener tListener) {
mListener = tListener;
}
public ChangeListener getListener() {
return mListener;
}
public void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
}
Usage:
public static void init() {
MonitoredVariable.ChangeListener tUpdateBackground = new MonitoredVariable.ChangeListener() {
#Override
public void onChange() { updateBackgroud();
}
};
mTop = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mBottom = new MonitoredVariable[]{
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground),
new MonitoredVariable<>(0, tUpdateBackground)
};
mAnimationLoop = new Handler();
mAnimation = new Runnable() {
#Override
public void run() {
Debug.Log(TAG, "RUNNING ANIMATION");
final Random RNG = new Random();
for (MonitoredVariable<Integer>[] tBackground: new MonitoredVariable[][] {mTop, mBottom}) {
for (MonitoredVariable<Integer> tColor : tBackground) {
int tRandomColor = RNG.nextInt(255);
//tColor.set(tRandomColor);
Shift.changeOverTime(tColor, tRandomColor, 2000, 100);
}
}
if(mAnimate.get()) {
mAnimationLoop.postDelayed(mAnimation, 10000);
}
}
};
mAnimate = new MonitoredVariable<>(false, new MonitoredVariable.ChangeListener() {
#Override
public void onChange() {
if (mAnimate.get()) mAnimationLoop.postDelayed(mAnimation, 0);
else mAnimationLoop.removeCallbacks(mAnimation);
}
});
}
public static void setBackground(final Activity tActivity){
final View tActivityBackground = tActivity.findViewById(R.id.background);
mListener = new ChangeListener() {
#Override
public void onChange() { tActivityBackground.setBackground(mBackground); }
};
notifyChange();
}
private static void updateBackgroud() {
int tTop = Color.argb(255, mTop[0].get(), mTop[1].get(), mTop[2].get());
int tBottom = Color.argb(255, mBottom[0].get(), mBottom[1].get(), mBottom[2].get());
int[] colors = {tTop, tBottom};
mBackground = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
mBackground.setCornerRadius(0f);
notifyChange();
}
public static void animateBackground(boolean tAnimate) {
mAnimate.set(tAnimate);
}
public static void notifyChange() {
if (mListener != null) mListener.onChange();
}
public interface ChangeListener {
void onChange();
}
I had this error on my VoiSip Application
E/AudioRecord: AudioFlinger could not create record track, status: -1
E/AudioGroup: cannot initialize audio device
This error occurs after I'm trying to make call to another sip address
Here have 2 java class(WalkieTalkieActivity.java & IncomingCallReceiver.java)
WalkieTalkieActivity.java
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public IncomingCallReceiver callReceiver;
public SipManager mSipManager = null;
public SipProfile mSipProfile = null;
public SipAudioCall call = null;
TextView tv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
if (mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
tv = (TextView)findViewById(R.id.textView);
}
#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();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void closeLocalProfile() {
if (mSipManager == null) {
return;
}
try {
if (mSipProfile != null) {
mSipManager.close(mSipProfile.getUriString());
}
} catch (Exception ee) {
Log.d("onDestroy", "Failed to close local profile.", ee);
}
}
public void initializeManager() {
if(mSipManager == null) {
mSipManager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
private void initializeLocalProfile() {
String domain = "mydomain";
String username = "myusername";
String password = "mypassword";
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setPassword(password);
mSipProfile = builder.build();
if (mSipProfile == null){
Log.e("error cukimai", "null");
}else{
Log.e("error cukimai", "not null");
}
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
mSipManager.open(mSipProfile, pi, null);
mSipManager.setRegistrationListener(mSipProfile.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
Log.e("process","Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
Log.e("process","ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
Log.e("process","Registration failed. Please check settings.");
}
});
Log.e("process","stop");
} catch (SipException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk cuk");
} catch (ParseException e) {
e.printStackTrace();
Log.e("error cukimai", "cuk");
}
}
public void updateStatus(final String st){
this.runOnUiThread(new Runnable() {
public void run() {
tv.setText(st);
}
});
}
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
public void callAct(View view) {
Toast.makeText(this, "about to make call", Toast.LENGTH_LONG).show();
makeCall();
}
public void makeCall(){
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = mSipManager.makeAudioCall(mSipProfile.getUriString(), "sip:destination#domain", listener, 30);
Log.e("make call", "true");
start();
}catch (Exception e){
Log.i("error", "Error when trying to close manager.", e);
if (mSipProfile != null) {
try {
mSipManager.close(mSipProfile.getUriString());
} catch (Exception ee) {
Log.i("error", "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
#Override
public boolean onTouch(View view, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
final MediaRecorder recorder = new MediaRecorder();
final String path;
/**
* Creates a new audio recording at the given path (relative to root of SD card).
*/
public WalkieTalkieActivity(String path) {
this.path = sanitizePath(path);
}
private String sanitizePath(String path) {
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.contains(".")) {
path += ".3gp";
}
return Environment.getExternalStorageDirectory().getAbsolutePath() + path;
}
/**
* Starts a new recording.
*/
public void start() throws IOException {
String state = android.os.Environment.getExternalStorageState();
if(!state.equals(android.os.Environment.MEDIA_MOUNTED)) {
throw new IOException("SD Card is not mounted. It is " + state + ".");
}
// make sure the directory we plan to store the recording in exists
File directory = new File(path).getParentFile();
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Path to file could not be created.");
}
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile(path);
recorder.prepare();
recorder.start();
}
/**
* Stops a recording that has been previously started.
*/
public void stop() throws IOException {
recorder.stop();
recorder.release();
}
}
IncomingCallReceiver.java
public class IncomingCallReceiver extends BroadcastReceiver {
/**
* Processes the incoming call, answers it, and hands it over to the
* WalkieTalkieActivity.
* #param context The context under which the receiver is running.
* #param intent The intent being received.
*/
#Override
public void onReceive(Context context, Intent intent) {
SipAudioCall incomingCall = null;
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onRinging(SipAudioCall call, SipProfile caller) {
try {
call.answerCall(30);
} catch (Exception e) {
e.printStackTrace();
}
}
};
WalkieTalkieActivity wtActivity = (WalkieTalkieActivity) context;
incomingCall = wtActivity.mSipManager.takeAudioCall(intent, listener);
incomingCall.answerCall(30);
incomingCall.startAudio();
incomingCall.setSpeakerMode(true);
if(incomingCall.isMuted()) {
incomingCall.toggleMute();
}
wtActivity.call = incomingCall;
wtActivity.updateStatus(incomingCall);
} catch (Exception e) {
if (incomingCall != null) {
incomingCall.close();
}
}
}
}
I'm really new on Sip and Voip Implementing in Android Studio. I got this code from google source code.
I believe this error occurs because of the use of hardware (audio). However I have been searching on google for almost 1 week and not giving results. Can someone help me?
I had same problem but when i changed targetSdkVersion to 12 in build.gradel its fixed.
and this answer helped me to fixed problem .
You must choose the BufferSize when you want to record or call in app. For example:
int bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
if (bufferSize > 0 && bufferSize <= 256){
bufferSize = 256;
}else if (bufferSize > 256 && bufferSize <= 512){
bufferSize = 512;
}else if (bufferSize > 512 && bufferSize <= 1024){
bufferSize = 1024;
}else if (bufferSize > 1024 && bufferSize <= 2048){
bufferSize = 2048;
}else if (bufferSize > 2048 && bufferSize <= 4096){
bufferSize = 4096;
}else if (bufferSize > 4096 && bufferSize <= 8192){
bufferSize = 8192;
}else if (bufferSize > 8192 && bufferSize <= 16384){
bufferSize = 16384;
}else{
bufferSize = AudioRecord.getMinBufferSize(rate, channelConfig, audioFormat);
}
I have an app that makes use of an xml obtained with a HttpGet. In the url of the xml request has a key that changes every hour, this key is obtained through another url.
Example: www.test.com/xml?hr=123456
The app tries to get the xml. If errors occur, get the key in another HttpGet and updates in the xml url.
In the emulator works perfectly, but not on the device. Already put a trace and the key is successfully updated. But the xml request error continues.
I tried to put "no cache" in HttpGet
HttpClient client = new DefaultHttpClient (httpParams);
HttpGet get = new HttpGet (url);
get.addHeader ("Cache-Control", "no-cache"); / / HTTP/1.1
get.addHeader ("Expires", "Sat, 26 Jul 1997 05:00:00 GMT");
but it did not work, is there anything that can be done?
My Complete Activity:
public class ShowActivity extends AdModctivity implements
bbbAndroidConstantes, OnItemClickListener, OnCheckedChangeListener {
private ProgressDialog dialog;
private Retf p;
private Handler handler = new Handler();
private Exception ex;
private CheckBox check;
private ParametrosTO parTO;
ParametrosDataBase parDB;
String ref;
String pId;
String logR;
String kId;
String ldesc;
TextView txtRef;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listaprevisoeslayout);
Bundle bundle = getIntent().getExtras();
parDB = new ParametrosDataBase(this);
parTO = parDB.listParametros();
pId = bundle.getString(VAR_P_ID);
ref = bundle.getString(VAR_P_REF);
logR = bundle.getString(VAR_LOGR);
kId = bundle.getString(VAR_KID);
ldesc = bundle.getString(VAR_LDESC);
txtRef = (TextView) findViewById(R.id.txtRef);
check = (CheckBox) findViewById(R.id.checkWidget);
WidgetDataBase wDb = new WidgetDataBase(this);
if (wDb.searchWidget(pId, kId) != null)
check.setChecked(true);
check.setOnCheckedChangeListener(this);
dialog = ProgressDialog.show(ShowActivity.this, "",
"Wait...", true);
if (!Utilities.chkStatus(ShowActivity.this))
return;
downloadInfo();
fillAdMod();
}
#Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
}
private void downloadInfo() {
new Thread() {
#Override
public void run() {
boolean flag = false;
try {
p = Controller.getInstance().getRetf(parTO.getUrl(), pId, kId);
if ((p.getInfoP() == null) || (p.getInfoP().size() == 0)) {
flag = true;
String newUrl = getNewUrl();
Utilities.updateUrl(ShowActivity.this, newUrl);
parTO = parDB.listParametros();
p = Controller.getInstance().getRetf(newUrl, pId, kId);
}
refreshScreen();
} catch (Exception e) {
if (!flag) {
try {
String newUrl = getNewUrl();
Utilities.updateUrl(ShowActivity.this, newUrl);
parTO = parDB.listParametros();
p = Controller.getInstance().getRetf(newUrl, pId, kId);
refreshScreen();
} catch (Exception e1) {
ex = e1;
refreshScreenException();
}
}
else
{
ex = e;
refreshScreenException();
}
}
}
}.start();
}
/**
* Thread to close dialog and show information
*/
private void refreshScreen() {
handler.post(new Runnable() {
#Override
public void run() {
dialog.dismiss();
fillInfo();
}
});
}
/**
* Thread to close dialog and show exception
*/
private void refreshScreenException() {
handler.post(new Runnable() {
#Override
public void run() {
dialog.dismiss();
fillInfoExcecao();
}
});
}
/**
* Fill information on screen
*/
private void fillInfo() {
if (p == null) {
Toast.makeText(ShowActivity.this, MSG_SEM_Retf,
MSG_TIME_MILIS).show();
this.finish();
}
if ((p.getErro() != null) && (p.getErro().trim().length() > 0)) {
Toast.makeText(ShowActivity.this, p.getErro(),
MSG_TIME_MILIS).show();
this.finish();
}
if ((p.getPonto() == null) || (p.getPonto().size() == 0)) {
Toast.makeText(ShowActivity.this, MSG_SEM_Retf,
MSG_TIME_MILIS).show();
this.finish();
}
SimpleDateFormat spf = new SimpleDateFormat("HH:mm:ss");
long localTime = Long.parseLong(p.getLocalTime());
txtRef.setText(txtRef.getText() + " "
+ spf.format(new Date(localTime)));
RetfAdapter RetfAdapter = new RetfAdapter(this, p);
ListView lista = (ListView) findViewById(R.id.listView1);
lista.setAdapter(RetfAdapter);
lista.setOnItemClickListener(this);
}
/**
* Apresenta mensagem em caso de exceo
*/
private void fillInfoExcecao() {
if (ex instanceof bbbException) {
Toast.makeText(ShowActivity.this,
((bbbException) ex).getMessage(), MSG_TIME_MILIS).show();
ShowActivity.this.finish();
} else {
Toast.makeText(ShowActivity.this,
getString(R.string.msg_erroSistema), MSG_TIME_MILIS).show();
ShowActivity.this.finish();
}
}
#Override
public void onCheckedChanged(CompoundButton cb, boolean isChecked) {
PBean PBean = new PBean(pId, logR,
ref, kId, ldesc);
WidgetDataBase wDb = new WidgetDataBase(this);
if (isChecked)
wDb.addWidget(PBean);
else
wDb.deleteWidget(PBean);
}
private String getNewUrl() throws Exception
{
String newUrl = Utilities.getHttp(bbbAndroidConstantes.URL_HOST_HORARIOS);
return newUrl;
}
}