我在MainActivity中有一些方法并尝试从片段访问。但该活动显示为空。
MainActivity.java
public class MainActivity extends AppCompatActivity implements
PermissionResultListener, SwipeRefreshLayout.OnRefreshListener {
public boolean requestPermissionStorage() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(getString(R.string.storage_permission_request_title))
.setMessage(getString(R.string.storage_permission_request_summary))
.setNeutralButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
Const.EXTDIR_REQUEST_CODE);
}
})
.setCancelable(false);
alert.create().show();
return false;
}
return true;
}
@TargetApi(23)
public void requestSystemWindowsPermission() {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, Const.SYSTEM_WINDOWS_CODE);
}
}
@TargetApi(23)
private void setSystemWindowsPermissionResult() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (Settings.canDrawOverlays(this)) {
mPermissionResultListener.onPermissionResult(Const.SYSTEM_WINDOWS_CODE,
new String[]{"System Windows Permission"},
new int[]{PackageManager.PERMISSION_GRANTED});
} else {
mPermissionResultListener.onPermissionResult(Const.SYSTEM_WINDOWS_CODE,
new String[]{"System Windows Permission"},
new int[]{PackageManager.PERMISSION_DENIED});
}
} else {
mPermissionResultListener.onPermissionResult(Const.SYSTEM_WINDOWS_CODE,
new String[]{"System Windows Permission"},
new int[]{PackageManager.PERMISSION_GRANTED});
}
}
public void requestPermissionAudio() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.RECORD_AUDIO},
Const.AUDIO_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case Const.EXTDIR_REQUEST_CODE:
if ((grantResults.length > 0) &&
(grantResults[0] != PackageManager.PERMISSION_GRANTED)) {
Log.d(Const.TAG, "write storage Permission Denied");
fab.setEnabled(false);
} else {
Log.d(Const.TAG, "write storage Permission granted");
createDir();
}
}
if (mPermissionResultListener != null) {
mPermissionResultListener.onPermissionResult(requestCode, permissions, grantResults);
}
}
public void setPermissionResultListener(PermissionResultListener mPermissionResultListener) {
this.mPermissionResultListener = mPermissionResultListener;
}
}
SettingActivity.java
public class SettingActivity extends AppCompatPrefernceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsPreferenceFragment()).commit();
}
public static class SettingsPreferenceFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener
, PermissionResultListener, OnDirectorySelectedListerner {
/**
* SharedPreferences object to read the persisted settings
*/
SharedPreferences prefs;
/**
* ListPreference to choose the recording resolution
*/
private ListPreference res;
/**
* CheckBoxPreference to manage audio recording via mic setting
*/
private CheckBoxPreference recaudio;
/**
* CheckBoxPreference to manage onscreen floating control setting
*/
private CheckBoxPreference floatingControl;
/**
* FolderChooser object to choose the directory where the video has to be saved to.
*/
private FolderChooser dirChooser;
/**
* MainActivity object
*/
private MainActivity activity;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activity = (MainActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " Not MainActivity class instance");
}
}
/**
* Initialize various listeners and settings preferences.
*
* @param savedInstanceState default savedInstance bundle sent by Android runtime
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
setPermissionListener();
String defaultSaveLoc = (new File(Environment
.getExternalStorageDirectory() + File.separator + Const.APPDIR)).getPath();
prefs = getPreferenceScreen().getSharedPreferences();
res = (ListPreference) findPreference(getString(R.string.res_key));
ListPreference fps = (ListPreference) findPreference(getString(R.string.fps_key));
ListPreference bitrate = (ListPreference) findPreference(getString(R.string.bitrate_key));
recaudio = (CheckBoxPreference) findPreference(getString(R.string.audiorec_key));
ListPreference filenameFormat = (ListPreference) findPreference(getString(R.string.filename_key));
EditTextPreference filenamePrefix = (EditTextPreference) findPreference(getString(R.string.fileprefix_key));
dirChooser = (FolderChooser) findPreference(getString(R.string.savelocation_key));
floatingControl = (CheckBoxPreference) findPreference(getString(R.string.preference_floating_control_key));
CheckBoxPreference touchPointer = (CheckBoxPreference) findPreference("touch_pointer");
//Set previously chosen directory as initial directory
dirChooser.setCurrentDir(getValue(getString(R.string.savelocation_key), defaultSaveLoc));
ListPreference theme = (ListPreference) findPreference(getString(R.string.preference_theme_key));
theme.setSummary(theme.getEntry());
//Set the summary of preferences dynamically with user choice or default if no user choice is made
updateScreenAspectRatio();
updateResolution(res);
fps.setSummary(getValue(getString(R.string.fps_key), "30"));
float bps = bitsToMb(Integer.parseInt(getValue(getString(R.string.bitrate_key), "7130317")));
bitrate.setSummary(bps + " Mbps");
dirChooser.setSummary(getValue(getString(R.string.savelocation_key), defaultSaveLoc));
filenameFormat.setSummary(getFileSaveFormat());
filenamePrefix.setSummary(getValue(getString(R.string.fileprefix_key), "recording"));
//If record audio checkbox is checked, check for record audio permission
if (recaudio.isChecked())
requestAudioPermission();
//If floating controls is checked, check for system windows permission
if (floatingControl.isChecked())
requestSystemWindowsPermission();
//set callback for directory change
dirChooser.setOnDirectoryClickedListerner(this);
}
/**
* Updates the summary of resolution settings preference
*
* @param pref object of the resolution ListPreference
*/
private void updateResolution(ListPreference pref) {
pref.setSummary(getValue(getString(R.string.res_key), getNativeRes()));
}
/**
* Method to get the device's native resolution
*
* @return device resolution
*/
private String getNativeRes() {
DisplayMetrics metrics = getRealDisplayMetrics();
return getScreenWidth(metrics) + "x" + getScreenHeight(metrics);
}
/**
* Updates the available resolution based on aspect ratio
*/
private void updateScreenAspectRatio() {
Const.ASPECT_RATIO aspect_ratio = getAspectRatio();
Log.d(Const.TAG, "Aspect ratio: " + aspect_ratio);
CharSequence[] entriesValues = getResolutionEntriesValues(aspect_ratio);
res.setEntries(entriesValues);
res.setEntryValues(entriesValues);
}
/**
* Get resolutions based on the device's aspect ratio
*
* @param aspectRatio {@link com.orpheusdroid.screenrecorder.Const.ASPECT_RATIO} of the device
* @return entries for the resolution
*/
private CharSequence[] getResolutionEntriesValues(Const.ASPECT_RATIO aspectRatio) {
ArrayList<String> entries;
switch (aspectRatio) {
case AR16_9:
entries = buildEntries(R.array.resolutionsArray_16_9);
break;
case AR18_9:
entries = buildEntries(R.array.resolutionValues_18_9);
break;
default:
entries = buildEntries(R.array.resolutionsArray_16_9);
break;
}
String[] entriesArray = new String[entries.size()];
return entries.toArray(entriesArray);
}
/**
* Build resolutions from the arrays.
*
* @param resID resource ID for the resolution array
* @return ArrayList of available resolutions
*/
private ArrayList<String> buildEntries(int resID) {
DisplayMetrics metrics = getRealDisplayMetrics();
int width = getScreenWidth(metrics);
int height = getScreenHeight(metrics);
String nativeRes = width + "x" + height;
ArrayList<String> entries = new ArrayList<>(Arrays.asList(getResources().getStringArray(resID)));
Iterator<String> entriesIterator = entries.iterator();
while (entriesIterator.hasNext()) {
String entry = entriesIterator.next();
String[] widthHeight = entry.split("x");
if (width < Integer.parseInt(widthHeight[0]) || height < Integer.parseInt(widthHeight[1])) {
entriesIterator.remove();
}
}
if (!entries.contains(nativeRes))
entries.add(nativeRes);
return entries;
}
/**
* Returns object of DisplayMetrics
*
* @return DisplayMetrics
*/
private DisplayMetrics getRealDisplayMetrics(){
DisplayMetrics metrics = new DisplayMetrics();
WindowManager window = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
window.getDefaultDisplay().getRealMetrics(metrics);
return metrics;
}
/**
* Get width of screen in pixels
*
* @return screen width
*/
private int getScreenWidth(DisplayMetrics metrics) {
return metrics.widthPixels;
}
/**
* Get height of screen in pixels
*
* @return Screen height
*/
private int getScreenHeight(DisplayMetrics metrics) {
return metrics.heightPixels;
}
/**
* Get aspect ratio of the screen
*/
private Const.ASPECT_RATIO getAspectRatio() {
float screen_width = getScreenWidth(getRealDisplayMetrics());
float screen_height = getScreenHeight(getRealDisplayMetrics());
float aspectRatio;
if (screen_width > screen_height) {
aspectRatio = screen_width / screen_height;
} else {
aspectRatio = screen_height / screen_width;
}
return Const.ASPECT_RATIO.valueOf(aspectRatio);
}
/**
* Set permission listener in the {@link MainActivity} to handle permission results
*/
private void setPermissionListener() {
if (getActivity() != null && getActivity() instanceof MainActivity) {
activity = (MainActivity) getActivity();
activity.setPermissionResultListener(this);
}
}
/**
* Get the persisted value for the preference from default sharedPreference
*
* @param key String represnting the sharedpreference key to fetch
* @param defVal String Default value if the preference does not exist
* @return String the persisted preference value or default if not found
*/
private String getValue(String key, String defVal) {
return prefs.getString(key, defVal);
}
/**
* Method to convert bits per second to MB/s
*
* @param bps float bitsPerSecond
* @return float
*/
private float bitsToMb(float bps) {
return bps / (1024 * 1024);
}
//Register for OnSharedPreferenceChangeListener when the fragment resumes
@Override
public void onResume() {
super.onResume();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
}
//Unregister for OnSharedPreferenceChangeListener when the fragment pauses
@Override
public void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
//When user changes preferences, update the summary accordingly
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
Preference pref = findPreference(s);
if (pref == null) return;
switch (pref.getTitleRes()) {
case R.string.preference_resolution_title:
updateResolution((ListPreference) pref);
break;
case R.string.preference_fps_title:
String fps = String.valueOf(getValue(getString(R.string.fps_key), "30"));
pref.setSummary(fps);
break;
case R.string.preference_bit_title:
float bps = bitsToMb(Integer.parseInt(getValue(getString(R.string.bitrate_key), "7130317")));
pref.setSummary(bps + " Mbps");
break;
case R.string.preference_filename_format_title:
pref.setSummary(getFileSaveFormat());
break;
case R.string.preference_audio_record_title:
requestAudioPermission();
break;
case R.string.preference_filename_prefix_title:
EditTextPreference etp = (EditTextPreference) pref;
etp.setSummary(etp.getText());
ListPreference filename = (ListPreference) findPreference(getString(R.string.filename_key));
filename.setSummary(getFileSaveFormat());
break;
case R.string.preference_floating_control_title:
requestSystemWindowsPermission();
break;
case R.string.preference_show_touch_title:
CheckBoxPreference showTouchCB = (CheckBoxPreference)pref;
if (showTouchCB.isChecked() && !hasPluginInstalled()){
showTouchCB.setChecked(false);
showDownloadAlert();
}
break;
case R.string.preference_crash_reporting_title:
CheckBoxPreference crashReporting = (CheckBoxPreference)pref;
CheckBoxPreference anonymousStats = (CheckBoxPreference) findPreference(getString(R.string.preference_anonymous_statistics_key));
if(!crashReporting.isChecked())
anonymousStats.setChecked(false);
break;
case R.string.preference_anonymous_statistics_title:
break;
case R.string.preference_theme_title:
activity.recreate();
break;
}
}
/**
* show an alert to download the plugin when the plugin is not found
*/
private void showDownloadAlert() {
new AlertDialog.Builder(getActivity())
.setTitle(R.string.alert_plugin_not_found_title)
.setMessage(R.string.alert_plugin_not_found_message)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
try {
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=com.orpheusdroid.screencamplugin")));
} catch (android.content.ActivityNotFoundException e) { // if there is no Google Play on device
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=com.orpheusdroid.screencamplugin")));
}
}
})
.setNeutralButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.create().show();
}
/**
* Check if "show touches" plugin is installed.
*
* @return boolean
*/
private boolean hasPluginInstalled(){
PackageManager pm = getActivity().getPackageManager();
try {
pm.getPackageInfo("com.orpheusdroid.screencamplugin",PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
Log.d(Const.TAG, "Plugin not installed");
return false;
}
return true;
}
/**
* Method to concat file prefix with dateTime format
*/
public String getFileSaveFormat() {
String filename = prefs.getString(getString(R.string.filename_key), "yyyyMMdd_hhmmss");
String prefix = prefs.getString(getString(R.string.fileprefix_key), "recording");
return prefix + "_" + filename;
}
/**
* Method to request android permission to record audio
*/
public void requestAudioPermission() {
if (activity != null) {
activity.requestPermissionAudio();
}
}
/**
* Method to request android system windows permission to show floating controls
* <p>
* Shown only on devices above api 23 (Marshmallow)
* </p>
*/
private void requestSystemWindowsPermission() {
if (activity != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
activity.requestSystemWindowsPermission();
} else {
Log.d(Const.TAG, "API is < 23");
}
}
/**
* Show snackbar with permission Intent when the user rejects write storage permission
*/
private void showSnackbar() {
Snackbar.make(getActivity().findViewById(R.id.fab), R.string.snackbar_storage_permission_message,
Snackbar.LENGTH_INDEFINITE).setAction(R.string.snackbar_storage_permission_action_enable,
new View.OnClickListener() {
@Override
public void onClick(View v) {
if (activity != null){
activity.requestPermissionStorage();
}
}
}).show();
}
/**
* Show a dialog when the permission to storage is denied by the user during startup
*/
private void showPermissionDeniedDialog(){
new AlertDialog.Builder(activity)
.setTitle(R.string.alert_permission_denied_title)
.setMessage(R.string.alert_permission_denied_message)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if (activity != null){
activity.requestPermissionStorage();
}
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
showSnackbar();
}
})
.setIconAttribute(android.R.attr.alertDialogIcon)
.setCancelable(false)
.create().show();
}
//Permission result callback to process the result of Marshmallow style permission request
@Override
public void onPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case Const.EXTDIR_REQUEST_CODE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_DENIED)) {
Log.d(Const.TAG, "Storage permission denied. Requesting again");
dirChooser.setEnabled(false);
showPermissionDeniedDialog();
} else if((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)){
dirChooser.setEnabled(true);
}
return;
case Const.AUDIO_REQUEST_CODE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Log.d(Const.TAG, "Record audio permission granted.");
recaudio.setChecked(true);
} else {
Log.d(Const.TAG, "Record audio permission denied");
recaudio.setChecked(false);
}
return;
case Const.SYSTEM_WINDOWS_CODE:
if ((grantResults.length > 0) && (grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
Log.d(Const.TAG, "System Windows permission granted");
floatingControl.setChecked(true);
} else {
Log.d(Const.TAG, "System Windows permission denied");
floatingControl.setChecked(false);
}
default:
Log.d(Const.TAG, "Unknown permission request with request code: " + requestCode);
}
}
@Override
public void onDirectorySelected() {
Log.d(Const.TAG, "In settings fragment");
if (getActivity() != null && getActivity() instanceof MainActivity) {
((MainActivity) getActivity()).onDirectoryChanged();
}
}
}
我正在尝试使用MainActivity中提到的方法从片段中获取运行时权限。但是activity = getActivity()显示为null。
我尝试在片段中使用onAttach方法,它也无法显示类强制转换异常。
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
activity = (MainActivity) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " Not MainActivity class instance");
}
}
答案 0 :(得分:0)
由于settingActivity是Fragment的容器,除非mainactivity是片段的容器,否则你无法从mainactivity获取上下文。
解决方案 - 您可以将函数设置为静态或将其写入扩展的应用程序类或设置活动