android - OnactivityResult Fragment বলা হচ্ছে না
android-fragments android-activity (20)
এই টুকরা হোস্টিং কার্যকলাপ ক্যামেরা কার্যকলাপ ফেরৎ যখন বলা হয় onActivityResult
।
আমার টুকরা একটি ছবি গ্রহণ করার জন্য প্রেরিত অভিপ্রায় ফলে একটি কার্যকলাপ শুরু হয়। ছবি আবেদন জরিমানা লোড, একটি ছবি লাগে, এবং আয়। onActivityResult
তবে আঘাত করা হয় না। আমি ব্রেকপয়েন্ট সেট করেছি, কিন্তু কিছুই ট্রিগার হয়। একটি টুকরা onActivityResult
থাকতে onActivityResult
? এটি একটি প্রদত্ত ফাংশন থেকে তাই আমি মনে করি। কেন এই হচ্ছে ট্রিগার করা হয় না?
ImageView myImage = (ImageView)inflatedView.findViewById(R.id.image);
myImage.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 1888);
}
});
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if( requestCode == 1888 ) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
((ImageView)inflatedView.findViewById(R.id.image)).setImageBitmap(photo);
}
}
আপনার পয়েন্ট
mention
হোস্ট কার্যকলাপ লঞ্চ মোড সেটsingleInstance
বা সেট করতে হবে না তা নিশ্চিত করুন যে এক পয়েন্ট কোন একsingleTask
।
OnActivityResult আপনার লঞ্চ মোড যদি SingleInstance বা SingleTask এ সেট থাকে তবে কাজ করবে না। অথবা আপনি এই অভিপ্রায় ফিল্টার ব্যবহার করে আপনার কার্যকলাপ কল
standard
বা singleTop
লঞ্চ মোড সূক্ষ্ম কাজ করবে।
ন্যস্ত ফ্যাগমেন্টের জন্য (উদাহরণস্বরূপ, একটি ভিউপ্যাজার ব্যবহার করার সময়)
আপনার প্রধান কার্যকলাপে:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
আপনার প্রধান শীর্ষ স্তরের টুকরা (ViewPager ফ্যাগমেন্ট):
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
YourFragment frag = (YourFragment) getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
frag.yourMethod(data); // Method for callback in YourFragment
super.onActivityResult(requestCode, resultCode, data);
}
আপনার ফ্র্যাগমেন্টে (নেস্টেড ফ্যাগমেন্ট):
public void yourMethod(Intent data){
// Do whatever you want with your data
}
Ollie C উল্লেখ করার পরে, যখন আপনি নেস্টেড টুকরাগুলি ব্যবহার করছেন তখন ফেরত মানগুলি অনঅ্যাক্টিভিটি রিসেলেটে সহায়তা লাইব্রেরির জন্য একটি সক্রিয় বাগ রয়েছে। আমি শুধু এটা আঘাত :-(।
অনেক নিখরচায় ফাংশনগুলির জন্য (উদাহরণস্বরূপ, একটি বিভাজনে একটি ভিউপ্যাজার ব্যবহার করার সময়)
আপনার প্রধান কার্যকলাপে :
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
আপনার টুকরা মধ্যে:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
for (Fragment fragment : getChildFragmentManager().getFragments()) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
আপনার নিস্তেজ ফাটল
কল কার্যকলাপ
getParentFragment().startActivityForResult(intent, uniqueInstanceInt);
uniqueInstanceInt - এটি একটি এনটি দিয়ে প্রতিস্থাপন করুন যা নেস্টেড টুকরাগুলির মধ্যে অনন্য যা অন্য ফ্যাগমেন্টকে উত্তর দেওয়ার জন্য প্রতিরোধ করে।
প্রতিক্রিয়া পান
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == uniqueInstanceInt ) {
// TODO your code
}
}
মনোযোগ
0 এবং 65536 এর মধ্যে একটি নম্বরকে অনন্যইনস্ট্যান্সটিতে ব্যবহার করতে হবে "ত্রুটি কোডের জন্য কম 16 বিট ব্যবহার করতে পারেন" এ ত্রুটিটি এড়ানোর জন্য।
আমার ক্ষেত্রে এটি একটি Android বাগ ছিল ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), যদি আপনি সমর্থিত FragmentActivity
ব্যবহার করেন তবে আপনাকে পরিবর্তে getSupportFragmentManager
ব্যবহার getSupportFragmentManager
হবে getChildFragmentManager
:
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if(fragment instanceof UserProfileFragment) {
fragment.onActivityResult(requestCode, resultCode, data);
}
}
}
আমার মনে হয় আপনি getActivity().startActivityForResult(intent,111);
। আপনি startActivityForResult(intent,111);
কল করা উচিত startActivityForResult(intent,111);
।
আমি ChildFragmentManager
সঙ্গে একই সমস্যা হচ্ছে। ম্যানেজারটি নেস্টেড ফ্যাগমেন্টে ফলাফলটি পাস করবে না, আপনাকে নিজের বেস টুকরোতে নিজে নিজে তা করতে হবে।
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag);
if (fragment != null) {
fragment.onActivityResult(requestCode, resultCode, intent);
}
}
আমি একই সমস্যার মুখোমুখি হয়েছিলাম যখন আমি কোডের এই ব্লকটি একটি parentActivity
বাইরে একটি ইউটিলিটি ক্লাসে স্থানান্তরিত করেছিলাম, parentActivity
যুক্তি হিসাবে পাস করেছিল,
Intent intent = new Intent(parentActivity, CameraCaptureActivity.class);
parentActivity.startActivityForResult(intent,requestCode);
তারপর আমি যে ফ্র্যাগমেন্টের onActivityResult
পদ্ধতিতে কোনও মান খুঁজে onActivityResult
, onActivityResult
, আমি ফ্র্যাগমেন্টে যুক্তি পরিবর্তন করেছিলাম, তাই পদ্ধতিটির সংশোধিত সংজ্ঞাটি দেখতে পেলাম,
Intent intent = new Intent(fragment.getContext(), CameraCaptureActivity.class);
fragment.startActivityForResult(intent,requestCode);
এর পর, আমি Fragment উপর onActivityResult
মধ্যে মান পেতে সক্ষম হয়েছিল
আমি শুধু একটি workaround পদ্ধতি করা:
public static Fragment _tempFragment = null;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(_tempFragment != null)
_tempFragment.onActivityResult(requestCode, resultCode, data);
}
আপনার ফ্র্যাগমেন্টে, শুরু করার আগে অ্যাক্টিভিটি রিসাল্ট সেট করুন
MainActivity._tempFragment = this;
অন অ্যাক্টিভিটি রিসাল্ট <- ফ্র্যাগমেন্টে
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Do your job
{
}
MainActivity._tempFragment = null;
}
এই উত্তরগুলি বেশিরভাগই বলে যে আপনার Fragment
জন্য আপনার হোস্ট Activity
super.onActivityResult(...)
কল করুন। কিন্তু যে আমার জন্য কাজ বলে মনে হচ্ছে না।
সুতরাং, আপনার হোস্ট Activity
আপনাকে আপনার Fragments
onActivityResult(...)
কল করতে হবে। এখানে একটি উদাহরণ।
public class HostActivity extends Activity {
private MyFragment myFragment;
protected void onActivityResult(...) {
super.onActivityResult(...);
this.myFragment.onActivityResult(...);
}
}
আপনার HostActivity
কোনও সময়ে আপনাকে এটি ব্যবহার করতে হবে। HostActivity
আপনি যে Fragment
ব্যবহার করছেন তা নির্ধারণ করুন। অথবা, আপনার HostActivity
এটির রেফারেন্স রাখার পরিবর্তে Fragment
HostActivity
। এছাড়াও, আপনি এই this.myFragment.onActivityResult(...);
কল করার চেষ্টা করার আগে null
জন্য চেক করুন this.myFragment.onActivityResult(...);
।
এটি সবচেয়ে জনপ্রিয় সমস্যা এক। আমরা এই সমস্যা সংক্রান্ত থ্রেড প্রচুর পাওয়া যাবে। কিন্তু তাদের কেউ আমার জন্য দরকারী।
তাই আমি এই সমাধান ব্যবহার করে এই সমস্যা সমাধান করেছি।
আসুন প্রথমে বুঝি কেন এই ঘটছে।
আমরা startActivityForResult
থেকে সরাসরি অ্যাক্টিভিটিফোরসেল্ট কল করতে পারি তবে আসলে পিছনে থাকা মেকানিকটি কার্যকলাপ দ্বারা পরিচালিত হয়।
একবার আপনি ফ্র্যাগমেন্ট থেকে startActivityForResult
কল করলে, অনুরোধ কোডটি কোডটিতে ফ্র্যাগমেন্টের পরিচয় সংযুক্ত করতে পরিবর্তিত হবে। যেটি কার্যকলাপটি একবার প্রাপ্ত হওয়ার পরে এই অনুরোধটি পাঠানোর জন্য ট্র্যাক করতে সক্ষম হবেন।
একবার ক্রিয়াকলাপটি নেভিগেট করা হয়ে গেলে, ফলাফলটি কার্যকলাপের অনঅ্যাক্টিভিটি রিসাল্টে সংশোধিত অনুরোধ কোড সহ পাঠানো হবে যা মূল অনুরোধকোড + ফ্র্যাগমেন্টের পরিচয়তে ডিকোড করা হবে। তারপরে, কার্যকলাপ অ্যাক্টিভিটি রিসাল্টের মাধ্যমে যে ফ্র্যাগমেন্টের ক্রিয়াকলাপ ফলাফল পাঠাবে। এবং এটা সব সম্পন্ন।
সমস্যা হল:
কার্যকলাপটি শুধুমাত্র ফাংশনটি প্রেরণ করতে পারে যা সরাসরি ক্রিয়াকলাপের সাথে সংযুক্ত করা হয়েছে তবে নিস্তেজ নয়। এ কারণেই নেস্টেড ফ্র্যাগমেন্টের অ্যাক্টিভিটি রিসাল্ট কোন ব্যাপারই না বলা যায়।
সমাধান:
1) নীচের কোড দ্বারা আপনার Fragment মধ্যে অভিপ্রায় শুরু করুন:
/** Pass your fragment reference **/
frag.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE = 12345
2) এখন আপনার অভিভাবক কার্যকলাপের মধ্যে ** onActivityResult()
অ্যাক্টিভিটি onActivityResult()
: **
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
আপনি এটি কাজ করতে পিতামাতার কার্যকলাপে এই কল করতে হবে।
3) আপনার টুকরা কল ইন:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
}
}
এটাই. এই সমাধান দিয়ে, এটি কোন একক ফাটল জন্য প্রয়োগ করা যেতে পারে কিনা এটি নিস্তেজ কিনা বা না। এবং হ্যাঁ, এটা সব ক্ষেত্রে জুড়ে! তাছাড়া, কোড এছাড়াও সুন্দর এবং পরিষ্কার।
কেউ যদি এটি তৈরি করতে না পারে তবে আমি দুটি পরামর্শ যুক্ত করতে পারি। ম্যানিফেস্ট.এক্সএমএল ফাইলে, নিশ্চিত হোন যে হোস্টিং কার্যকলাপ কখন কল করে এবং শুরু করার কার্যকলাপটি প্রমিত হিসাবে লঞ্চ মোড থাকে। নীচের বিবরণ দেখুন:
হোস্টিং কার্যকলাপের জন্য, যদি মিথ্যা হিসাবে কোন ইতিহাস সম্পত্তি সেট করুন
android:noHistory="false"
ক্রিয়াকলাপটি শুরু করার জন্য, যদি লঞ্চ মোডটি মান হিসাবে সেট করুন
android:launchMode="standard"
যদি উপরের সমস্যাটি ফেসবুকে লগইন করা হয় তবে আপনি নীচের কোডটি আপনার ফ্যাগমেন্টের পিতামাতার ক্রিয়াকলাপে ব্যবহার করতে পারেন:
Fragment fragment = getFragmentManager().findFragmentById(android.R.id.tabcontent);
fragment.onActivityResult(requestCode, resultCode, data);
বা:
Fragment fragment = getFragmentManager().findFragmentById("fragment id here");
fragment.onActivityResult(requestCode, resultCode, data);
এবং আপনার টুকরা মধ্যে নীচের কল যোগ করুন ...
callbackManager.onActivityResult(requestCode, resultCode, data);
শুধু খণ্ড জন্য নীচের কোড ব্যবহার করুন।
@Override
public void onOtherButtonClick(ActionSheet actionSheet, int index) {
if (index == 1)
{
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent,
"Select Picture"), 1);
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 1) {
if (requestCode == 1) {
Uri selectedImageUri = data.getData();
//selectedImagePath = getPath(selectedImageUri);
}
}
}
onActivityResult তার পিতা বা মাতা কল ছাড়া কল করবে।
সবচেয়ে সহজ পদ্ধতি হল আপনার ফাটল থেকে একটি ক্রিয়াকলাপ শুরু করা।
startActivity(ActivityName);
তারপরে, আপনি startActivityForResult(intent,"1");
কল করুন startActivityForResult(intent,"1");
আপনার কার্যকলাপ থেকে এবং আপনার কার্যকলাপ অ্যাক্টিভিটি onActivityResult
যোগ করুন
startActivityForResult(intent,"1");
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
fragment.onActivityResult(requestCode, resultCode, data);
// perform other activity result like fetching from Uris or handling cursors
finish(); // finish the activity will get to back to your fragment.
}
সমাধান 1:
কল শুরু করুন startActivityForResult(intent, REQUEST_CODE);
পরিবর্তে getActivity().startActivityForResult(intent, REQUEST_CODE);
।
সমাধান 2:
যখন শুরু startActivityForResult(intent, REQUEST_CODE);
এটিকে কার্যকলাপের onActivityResult(requestCode,resultcode,intent)
বলা হয় এবং তারপর আপনি requestCode, resultCode and intent
পাস করে requestCode, resultCode and intent
fragments onActivityResult()
কল করতে পারেন।
FragmentActivity
একটি পরিবর্তিত এক দ্বারা requestCode
প্রতিস্থাপন। তারপরে, যখন onActivityResult()
হবে, FragmentActivity
onActivityResult()
উচ্চ 16 বিট onActivityResult()
করে এবং মূল ফ্র্যাগমেন্টের সূচী পুনরুদ্ধার করে। এই প্রকল্পটি দেখুন:
যদি আপনার রুট লেভেলে কিছু টুকরা থাকে তবে কোন সমস্যা নেই। কিন্তু আপনার যদি নীচযুক্ত টুকরা থাকে , উদাহরণস্বরূপ Fragment
ভিতরে কয়েকটি ট্যাব সহ Fragment
, আপনি নিশ্চিত যে কোনও সমস্যার মুখোমুখি হবে (অথবা এটি ইতিমধ্যেই সম্মুখীন হবে)।
কারণ শুধুমাত্র একটি সূচক requestCode
ভিতরে সংরক্ষণ করা হয়। যে তার FragmentManager
ভেতরে Fragment
সূচক। যখন আমরা নেস্টেড টুকরা ব্যবহার করছি, সেখানে শিশু FragmentManager
গুলি আছে, যা তাদের নিজস্ব Fragments তালিকা আছে। সুতরাং, FragmentManager
থেকে শুরু করে, সূচকের সমগ্র চেইন সংরক্ষণ করা প্রয়োজন।
কিভাবে আমরা এই সমস্যা সমাধান করবেন? এই পোস্টে সাধারণ workaround সমাধান আছে ।
আপনার কোড একটি নিস্তেজ ফাটল আছে। Super.onActivityForResult কল করা হয় না
আপনি আপনার ফাটলটি থেকে যেকোনো ক্রিয়াকলাপকে সংশোধন করতে চান না এবং ফ্যাগমেন্ট শৃঙ্খলে প্রতিটি অংশকে কল করার কাছাকাছি একটি কাজ করতে চান না।
এখানে অনেক কাজ সমাধান এক। ফ্লাইতে একটি টুকরো তৈরি করুন এবং এটি সমর্থন ফ্যাগমেন্ট ম্যানেজারের সাথে সরাসরি কার্যকলাপে তারের। তারপর নতুন তৈরি ফাটল থেকে startActivityForResult কল।
private void get_UserEmail() {
if (view == null) {
return;
}
((TextView) view.findViewById(R.id.tvApplicationUserName))
.setText("Searching device for user accounts...");
final FragmentManager fragManager = getActivity().getSupportFragmentManager();
Fragment f = new Fragment() {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
startActivityForResult(AccountPicker.newChooseAccountIntent(null, null,
new String[]{"com.google"}, false, null, null, null, null), REQUEST_CODE_PICK_ACCOUNT);
}
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
String mEmail = "";
if (resultCode == Activity.RESULT_OK) {
if (data.hasExtra(AccountManager.KEY_ACCOUNT_NAME)) {
mEmail = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
}
}
if (mActivity != null) {
GoPreferences.putString(mActivity, SettingApplication.USER_EMAIL, mEmail);
}
doUser();
}
super.onActivityResult(requestCode, resultCode, data);
fragManager.beginTransaction().remove(this).commit();
}
};
FragmentTransaction fragmentTransaction = fragManager
.beginTransaction();
fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT);
fragmentTransaction.commit();
}
আপনি নেস্টেড টুকরা ব্যবহার করা হয়, তাহলে এটি কাজ করছে:
getParentFragment().startActivityForResult(intent, RequestCode);
এর পাশাপাশি, আপনাকে super.onActivityResult
পিতামাতার ক্রিয়াকলাপ থেকে কল করুন এবং ফ্যাগমেন্টের onActivityResult
পদ্ধতিটি পূরণ করুন ।
যদি onActivityResult
ফ্যাগমেন্ট ক্লাসের ভিতরে থাকা পদ্ধতিতে সমস্যা হয় এবং আপনি এমন কিছু আপডেট করতে চান যা ফ্র্যাগমেন্ট ক্লাসের ভিতরেও থাকে তবে ব্যবহার করুন:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == Activity.RESULT_OK)
{
// If the user had agreed to enabling Bluetooth,
// populate the ListView with all the paired devices.
this.arrayDevice = new ArrayAdapter<String>(this.getContext(), R.layout.device_item);
for(BluetoothDevice bd : this.btService.btAdapater.getBondedDevices())
{
this.arrayDevice.add(bd.getAddress());
this.btDeviceList.setAdapter(this.arrayDevice);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
শুধু this.variable
উপরে কোড দেখানো হিসাবে যোগ করুন । অন্যথায় পদ্ধতিটি অভিভাবক কার্যকলাপের মধ্যে বলা হবে এবং পরিবর্তনশীল বর্তমান ইনস্ট্যান্সের আপডেট হবে না।
আমি কোডের এই ব্লকটিকে ক্লাসে MainActivity
প্রতিস্থাপন this
করে HomeFragment
এবং ভেরিয়েবলগুলিকে স্থিতিশীল করেও এটি পরীক্ষা করেছি। আমি প্রত্যাশিত হিসাবে আমি ফলাফল পেয়েছিলাম।
সুতরাং আপনি যদি নিজের অংশটি প্রয়োগ করার জন্য ফ্যাগমেন্ট ক্লাসটি চান তবে onActivityResult
উপরের কোডের উদাহরণটি উত্তর।