[英]force close an activity in kitkat & lollipop but work in jellybean?
this is an app that play music simultaneously on multiple Android device whith wifi connections 这是一个可在多个Android设备上同时播放音乐和wifi连接的应用
there is 2 sections, one is dj player mode (the device that play music) and the other one is speaker mode 有两个部分,一个是dj播放器模式(播放音乐的设备),另一个是扬声器模式
dj play mode activity work good on android jelly bean (4.1,4.2,4.3) but on newer versions (4.4,5) force close occur dj播放模式活动在android jelly bean(4.1,4.2,4.3)上工作良好,但在较新版本(4.4,5)上强制关闭
what is the problem? 问题是什么?
the dj player activity dj播放器活动
package com.example.musicsaround.dj;
import java.io.File;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.net.wifi.p2p.WifiP2pManager.ActionListener;
import android.net.wifi.p2p.WifiP2pManager.Channel;
import android.net.wifi.p2p.WifiP2pManager.ChannelListener;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;
import com.example.musicsaround.R;
import com.example.musicsaround.Timer;
import com.example.musicsaround.Utilities;
import com.example.musicsaround.dj.ServerDeviceListFragment.DJFragmentListener;
public class DJActivity extends Activity implements ChannelListener,
DJFragmentListener
{
public final static int DJ_MODE = 15;
public static final String TAG = "DJ Mode Activity";
private WifiP2pManager manager;
private boolean channelRetried = false;
private boolean isWifiP2pEnabled = false;
private BroadcastReceiver receiver = null;
ProgressDialog progressDialog = null;
private Timer timer;
private CountDownTimer keepAliveTimer;
// Keep the Wifi Alive every 5 seconds
private static final int KEEPALIVE_INTERVAL = 5000;
// critical component for Wi-fi Direct connectivity
private Channel channel;
private final IntentFilter intentFilter = new IntentFilter();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dj);
// need these intent filters to catch the Wi-fi direct events
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter
.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
TextView txt_time = (TextView) this.findViewById(R.id.txt_dj_time);
// start a timer with 25 ms precision
this.timer = new Timer(Timer.DEFAULT_TIMER_PRECISION);
// asynchronous call to start a timer
this.timer.startTimer();
keepAliveTimer = new CountDownTimer(KEEPALIVE_INTERVAL,
KEEPALIVE_INTERVAL)
{
@Override
public void onTick(long millisUntilFinished)
{
}
@Override
public void onFinish()
{
enableWifi();
keepAliveTimer.start();
}
};
}
/** register the BroadcastReceiver with the intent values to be matched */
@Override
public void onResume()
{
super.onResume();
receiver = new ServerWiFiDirectBR(manager, channel, this);
registerReceiver(receiver, intentFilter);
// ***Start discovering right away!
discoverDevices();
keepAliveTimer.start();
}
public void enableWifi()
{
WifiManager wifiManager = (WifiManager) this
.getSystemService(this.WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
}
/**
* UI to show the discovery process
*/
public void onInitiateDiscovery()
{
if (progressDialog != null && progressDialog.isShowing())
{
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(this, "Press back to cancel",
"finding peers", true, true,
new DialogInterface.OnCancelListener()
{
@Override
public void onCancel(DialogInterface dialog)
{
// stop discovery
manager.stopPeerDiscovery(channel,
new WifiP2pManager.ActionListener()
{
@Override
public void onFailure(int reason)
{
// Toast.makeText(DJActivity.this,
// "Stopping Discovery Failed : " +
// reason,
// Toast.LENGTH_SHORT).show();
Log.e(TAG,
"Stopping Discovery Failed. Error Code is: "
+ reason);
}
@Override
public void onSuccess()
{
Log.d(TAG, "Discovery stopped.");
}
});
}
});
}
public void discoverDevices()
{
// TODO: need a better non-blocking UI to notify users we are
// discovering
// onInitiateDiscovery();
// first turn on the wifi p2p
enableWifi();
channelRetried = false;
manager.discoverPeers(channel, new WifiP2pManager.ActionListener()
{
@Override
public void onSuccess()
{
// Toast.makeText(DJActivity.this,
// "Discovery Initiated",
// Toast.LENGTH_SHORT).show();
Log.d(TAG, "Discovery Initiated.");
}
// if we failed, then stop the discovery and start again
@Override
public void onFailure(int reasonCode)
{
Log.e(TAG, "Discovery Failed. Error Code is: " + reasonCode);
manager.stopPeerDiscovery(channel,
new WifiP2pManager.ActionListener()
{
@Override
public void onFailure(int reason)
{
// Toast.makeText(DJActivity.this,
// "Stopping Discovery Failed : " + reason,
// Toast.LENGTH_SHORT).show();
Log.e(TAG,
"Stopping Discovery Failed. Error Code is: "
+ reason);
}
@Override
public void onSuccess()
{
manager.discoverPeers(channel,
new WifiP2pManager.ActionListener()
{
@Override
public void onSuccess()
{
// Toast.makeText(DJActivity.this,
// "Discovery Initiated",
// Toast.LENGTH_SHORT)
// .show();
Log.d(TAG,
"Discovery Initiated.");
}
@Override
public void onFailure(int reasonCode)
{
Log.e(TAG,
"Discovery Failed. Error Code is: "
+ reasonCode);
}
});
}
});
}
});
}
@Override
public void onPause()
{
super.onPause();
unregisterReceiver(receiver);
keepAliveTimer.cancel();
}
@Override
public void onDestroy()
{
disconnect();
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.wifidirect_less, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.atn_direct_enable:
if (manager != null && channel != null)
{
// Since this is the system wireless settings activity, it's
// not going to send us a result. We will be notified by
// WiFiDeviceBroadcastReceiver instead.
Intent intent = new Intent();
// jump to wi-fi Direct settings
intent.setClassName("com.android.settings",
"com.android.settings.Settings$WifiP2pSettingsActivity");
startActivity(intent);
}
else
{
Log.e(TAG, "channel or manager is null");
}
return true;
case R.id.atn_direct_discover:
discoverDevices();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Remove all peers and clear all fields. This is called on
* BroadcastReceiver receiving a state change event. This is merely an UI
* update.
*/
public void resetDeviceList()
{
ServerDeviceListFragment fragmentList = (ServerDeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_djs_devices);
if (fragmentList != null)
{
fragmentList.clearPeers();
}
}
@Override
public void onChannelDisconnected()
{
// we will try once more
if (manager != null && !channelRetried)
{
Toast.makeText(this, "Wi-fi Direct Channel lost. Trying again...",
Toast.LENGTH_LONG).show();
resetDeviceList();
channelRetried = true;
manager.initialize(this, getMainLooper(), this);
}
else
{
Toast.makeText(
this,
"Wi-fi Direct Channel is still lost. Try disabling / re-enabling Wi-fi Direct in the P2P Settings.",
Toast.LENGTH_LONG).show();
}
}
@Override
public void showDetails(WifiP2pDevice device)
{
// TODO: This is for debugging, showing the device details
DJMusicFragment fragMusic = (DJMusicFragment) getFragmentManager()
.findFragmentById(R.id.frag_dj_music);
}
@Override
public void showInfo(WifiP2pInfo info)
{
DJMusicFragment fragMusic = (DJMusicFragment) getFragmentManager()
.findFragmentById(R.id.frag_dj_music);
if (info.isGroupOwner)
{
// fragMusic.setDebugText("I am the group owner.");
}
else
{
// fragMusic.setDebugText("I am not the group owner.");
}
}
/*
* Cancel an ongoing connection in progress. We won't actually use this
* method all that much
*
* (non-Javadoc)
*
* @see
* com.example.musicsaround.dj.ServerDeviceListFragment.DJFragmentListener
* #cancelDisconnect()
*/
@Override
public void cancelDisconnect()
{
/*
* A cancel abort request by user. Disconnect i.e. removeGroup if
* already connected. Else, request WifiP2pManager to abort the ongoing
* request
*/
if (manager != null)
{
Log.d(TAG, "Someone requested a cancel connect!");
final ServerDeviceListFragment fragment = (ServerDeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_djs_devices);
if (fragment.getDevice() == null
|| fragment.getDevice().status == WifiP2pDevice.CONNECTED)
{
// we don't disconnect the whole group... it would be nice just
// to disconnect that one guy
// disconnect();
}
else if (fragment.getDevice().status == WifiP2pDevice.AVAILABLE
|| fragment.getDevice().status == WifiP2pDevice.INVITED
|| fragment.getDevice().status == WifiP2pDevice.CONNECTED)
{
manager.cancelConnect(channel, new ActionListener()
{
@Override
public void onSuccess()
{
// Toast.makeText(DJActivity.this,
// "Aborting connection",
// Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reasonCode)
{
// Toast.makeText(
// DJActivity.this,
// "Connect abort request failed. Reason Code: "
// + reasonCode, Toast.LENGTH_SHORT)
// .show();
Log.e(TAG,
"Could not abort connection, the reason is: "
+ reasonCode);
}
});
}
}
}
/*
* This is the main method to connect to a device through Wi-Fi Direct!
*
* (non-Javadoc)
*
* @see
* com.example.musicsaround.dj.ServerDeviceListFragment.DJFragmentListener
* #connect(android.net.wifi.p2p.WifiP2pConfig)
*/
@Override
public void connect(WifiP2pConfig config)
{
if (manager == null)
{
return;
}
// in DJ mode, we want to become the group owner
WifiP2pConfig newConfig = config;
newConfig.groupOwnerIntent = DJ_MODE;
manager.connect(channel, newConfig, new ActionListener()
{
@Override
public void onSuccess()
{
// WiFiDirectBroadcastReceiver will notify us. Ignore for now.
}
@Override
public void onFailure(int reason)
{
Toast.makeText(DJActivity.this,
"Connection failed. Retrying...", Toast.LENGTH_SHORT)
.show();
Log.e(TAG,
"Wi-fi Direct connection failed. The error code is: "
+ reason);
}
});
}
@Override
public void disconnect()
{
if (manager == null)
{
return;
}
// TODO: why do we have to remove the whole group upon disconnect?
// perhaps we only need to do so upon exiting DJ mode
manager.removeGroup(channel, new ActionListener()
{
@Override
public void onFailure(int reasonCode)
{
Log.e(TAG, "Disconnect failed. Reason is: " + reasonCode);
}
@Override
public void onSuccess()
{
Toast.makeText(DJActivity.this, "Disconnected a device.",
Toast.LENGTH_SHORT).show();
Log.d(TAG, "Disconnected from a device.");
}
});
}
/**
* @param isWifiP2pEnabled
* the isWifiP2pEnabled to set
*/
public void setIsWifiP2pEnabled(boolean isWifiP2pEnabled)
{
this.isWifiP2pEnabled = isWifiP2pEnabled;
}
public void playRemoteMusic(Uri musicFileURI, long startTime, int startPos)
{
ServerDeviceListFragment fragmentList = (ServerDeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_djs_devices);
// convert URI to actual file path
Uri filePathFromActivity = Uri.parse(Utilities.getRealPathFromUri(
(Activity) this, musicFileURI));
File audioFile = new File(filePathFromActivity.getPath());
fragmentList.playMusicOnClients(audioFile, startTime, startPos);
}
public void playRemoteMusic(String musicFilePath, long startTime,
int startPos)
{
ServerDeviceListFragment fragmentList = (ServerDeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_djs_devices);
File audioFile = new File(musicFilePath);
fragmentList.playMusicOnClients(audioFile, startTime, startPos);
}
public void stopRemoteMusic()
{
ServerDeviceListFragment fragmentList = (ServerDeviceListFragment) getFragmentManager()
.findFragmentById(R.id.frag_djs_devices);
fragmentList.stopMusicOnClients();
}
public Timer getTimer()
{
return timer;
}
}
songsmanager: 歌曲管理员:
package com.example.musicsaround;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
public class SongsManager {
// SDCard Path
final String MEDIA_PATH = new String("/sdcard/Download");
private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
// Constructor
public SongsManager(){
}
/**
* Function to read all mp3 files from sdcard
* and store the details in ArrayList
* */
public ArrayList<HashMap<String, String>> getPlayList(){
File home = new File(MEDIA_PATH);
if (home.listFiles(new FileExtensionFilter()).length > 0) {
for (File file : home.listFiles(new FileExtensionFilter())) {
HashMap<String, String> song = new HashMap<String, String>();
song.put("songTitle", file.getName().substring(0, (file.getName().length() - 4)));
song.put("songPath", file.getPath());
// Adding each song to SongList
songsList.add(song);
}
}
// return songs list array
return songsList;
}
/**
* Class to filter files which are having .mp3 extension
* */
class FileExtensionFilter implements FilenameFilter {
public boolean accept(File dir, String name) {
return (name.endsWith(".mp3") || name.endsWith(".MP3"));
}
}
}
and logcat errors: 和logcat错误:
10-19 02:07:55.147: E/AndroidRuntime(1521): Process: com.example.musicsaround, PID: 1521
10-19 02:07:55.147: E/AndroidRuntime(1521): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.musicsaround/com.example.musicsaround.dj.DJActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread.access$800(ActivityThread.java:135)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.os.Handler.dispatchMessage(Handler.java:102)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.os.Looper.loop(Looper.java:136)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread.main(ActivityThread.java:5001)
10-19 02:07:55.147: E/AndroidRuntime(1521): at java.lang.reflect.Method.invokeNative(Native Method)
10-19 02:07:55.147: E/AndroidRuntime(1521): at java.lang.reflect.Method.invoke(Method.java:515)
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
10-19 02:07:55.147: E/AndroidRuntime(1521): at dalvik.system.NativeStart.main(Native Method)
10-19 02:07:55.147: E/AndroidRuntime(1521): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:713)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.Activity.setContentView(Activity.java:1929)
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.example.musicsaround.dj.DJActivity.onCreate(DJActivity.java:62)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.Activity.performCreate(Activity.java:5231)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)
10-19 02:07:55.147: E/AndroidRuntime(1521): ... 11 more
10-19 02:07:55.147: E/AndroidRuntime(1521): Caused by: java.lang.NullPointerException
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.example.musicsaround.SongsManager.getPlayList(SongsManager.java:25)
10-19 02:07:55.147: E/AndroidRuntime(1521): at com.example.musicsaround.dj.DJMusicFragment.onCreateView(DJMusicFragment.java:126)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.Fragment.performCreateView(Fragment.java:1700)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:866)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1040)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1142)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.app.Activity.onCreateView(Activity.java:4786)
10-19 02:07:55.147: E/AndroidRuntime(1521): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:689)
Its right in your log: 它在您的日志中正确:
9 02:07:55.147: E/AndroidRuntime(1521): Caused by: java.lang.NullPointerException 10-19 02:07:55.147: E/AndroidRuntime(1521): at com.example.musicsaround.SongsManager.getPlayList(SongsManager.java:25) 10-19 02:07:55.147: E/AndroidRuntime(1521): at com.example.musicsaround.dj.DJMusicFragment.onCreateView(DJMusicFragment.java:126) 9 02:07:55.147:E / AndroidRuntime(1521):原因:java.lang.NullPointerException 10-19 02:07:55.147:E / AndroidRuntime(1521):at com.example.musicsaround.SongsManager.getPlayList(SongsManager .java:25)10-19 02:07:55.147:E / AndroidRuntime(1521):at com.example.musicsaround.dj.DJMusicFragment.onCreateView(DJMusicFragment.java:126)
You got NullPointerException
at line 25 in your SongsManager
class at getPlayList
method. 在getPlayList
方法的SongsManager
类中的第25行获得NullPointerException
。
you can using FrameLayout instead of fragment 您可以使用FrameLayout而不是片段
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".DJActivity" >
<FrameLayout
android:id="@+id/frag_dj_music"
android:name="com.example.musicsaround.dj.DJMusicFragment"
android:layout_width="match_parent"
android:layout_height="300dp" />
<FrameLayout
android:id="@+id/frag_djs_devices"
android:name="com.example.musicsaround.dj.ServerDeviceListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:id="@+id/txt_dj_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DJ Time" />
</LinearLayout>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.