Android中的Parcel机制

  1. case BINDER_TYPE_BINDER:

  2. if (obj.binder) {

  3. LOG_REFS(“Parcel %p acquiring reference on local %p”, who, obj.cookie);

  4. static_cast<IBinder*>(obj.cookie)->incStrong(who);

  5. }

  6. return;

  7. case BINDER_TYPE_WEAK_BINDER:

  8. if (obj.binder)

  9. static_castRefBase::weakref\_type\*(obj.binder)->incWeak(who);

  10. return;

  11. case BINDER_TYPE_HANDLE: {

  12. const sp b = proc->getStrongProxyForHandle(obj.handle);

  13. if (b != NULL) {

  14. LOG_REFS(“Parcel %p acquiring reference on remote %p”, who, b.get());

  15. b->incStrong(who);

  16. }

  17. return;

  18. }

  19. case BINDER_TYPE_WEAK_HANDLE: {

  20. const wp b = proc->getWeakProxyForHandle(obj.handle);

  21. if (b != NULL) b.get_refs()->incWeak(who);

  22. return;

  23. }

  24. case BINDER_TYPE_FD: {

  25. // intentionally blank – nothing to do to acquire this, but we do

  26. // recognize it as a legitimate object type.

  27. return;

  28. }

  29. }

  30. LOGD(“Invalid object type 0x%08lx”, obj.type);

  31. }

  32. void release_object(const sp& proc,

  33. const flat_binder_object& obj, const void* who)

  34. {

  35. switch (obj.type) {

  36. case BINDER_TYPE_BINDER:

  37. if (obj.binder) {

  38. LOG_REFS(“Parcel %p releasing reference on local %p”, who, obj.cookie);

  39. static_cast<IBinder*>(obj.cookie)->decStrong(who);

  40. }

  41. return;

  42. case BINDER_TYPE_WEAK_BINDER:

  43. if (obj.binder)

  44. static_castRefBase::weakref\_type\*(obj.binder)->decWeak(who);

  45. return;

  46. case BINDER_TYPE_HANDLE: {

  47. const sp b = proc->getStrongProxyForHandle(obj.handle);

  48. if (b != NULL) {

  49. LOG_REFS(“Parcel %p releasing reference on remote %p”, who, b.get());

  50. b->decStrong(who);

  51. }

  52. return;

  53. }

  54. case BINDER_TYPE_WEAK_HANDLE: {

  55. const wp b = proc->getWeakProxyForHandle(obj.handle);

  56. if (b != NULL) b.get_refs()->decWeak(who);

  57. return;

  58. }

  59. case BINDER_TYPE_FD: {

  60. if (obj.cookie != (void*)0) close(obj.handle);

  61. return;

  62. }

  63. }

  64. LOGE(“Invalid object type 0x%08lx”, obj.type);

  65. }

  66. inline static status_t finish_flatten_binder(

  67. const sp& binder, const flat_binder_object& flat, Parcel* out)

  68. {

  69. return out->writeObject(flat, false);

  70. }

  71. status_t flatten_binder(const sp& proc,

  72. const sp& binder, Parcel* out)

  73. {

  74. flat_binder_object obj;

  75. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  76. if (binder != NULL) {

  77. IBinder *local = binder->localBinder();

  78. if (!local) {

  79. BpBinder *proxy = binder->remoteBinder();

  80. if (proxy == NULL) {

  81. LOGE(“null proxy”);

  82. }

  83. const int32_t handle = proxy ? proxy->handle() : 0;

  84. obj.type = BINDER_TYPE_HANDLE;

  85. obj.handle = handle;

  86. obj.cookie = NULL;

  87. } else {

  88. obj.type = BINDER_TYPE_BINDER;

  89. obj.binder = local->getWeakRefs();

  90. obj.cookie = local;

  91. }

  92. } else {

  93. obj.type = BINDER_TYPE_BINDER;

  94. obj.binder = NULL;

  95. obj.cookie = NULL;

  96. }

  97. return finish_flatten_binder(binder, obj, out);

  98. }

  99. status_t flatten_binder(const sp& proc,

  100. const wp& binder, Parcel* out)

  101. {

  102. flat_binder_object obj;

  103. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  104. if (binder != NULL) {

  105. sp real = binder.promote();

  106. if (real != NULL) {

  107. IBinder *local = real->localBinder();

  108. if (!local) {

  109. BpBinder *proxy = real->remoteBinder();

  110. if (proxy == NULL) {

  111. LOGE(“null proxy”);

  112. }

  113. const int32_t handle = proxy ? proxy->handle() : 0;

  114. obj.type = BINDER_TYPE_WEAK_HANDLE;

  115. obj.handle = handle;

  116. obj.cookie = NULL;

  117. } else {

  118. obj.type = BINDER_TYPE_WEAK_BINDER;

  119. obj.binder = binder.get_refs();

  120. obj.cookie = binder.unsafe_get();

  121. }

  122. return finish_flatten_binder(real, obj, out);

  123. }

  124. // XXX How to deal?  In order to flatten the given binder,

  125. // we need to probe it for information, which requires a primary

  126. // reference…  but we don’t have one.

  127. //

  128. // The OpenBinder implementation uses a dynamic_cast<> here,

  129. // but we can’t do that with the different reference counting

  130. // implementation we are using.

  131. LOGE(“Unable to unflatten Binder weak reference!”);

  132. obj.type = BINDER_TYPE_BINDER;

  133. obj.binder = NULL;

  134. obj.cookie = NULL;

  135. return finish_flatten_binder(NULL, obj, out);

  136. } else {

  137. obj.type = BINDER_TYPE_BINDER;

  138. obj.binder = NULL;

  139. obj.cookie = NULL;

  140. return finish_flatten_binder(NULL, obj, out);

  141. }

  142. }

  143. inline static status_t finish_unflatten_binder(

  144. BpBinder* proxy, const flat_binder_object& flat, const Parcel& in)

  145. {

  146. return NO_ERROR;

  147. }

  148. status_t unflatten_binder(const sp& proc,

  149. const Parcel& in, sp* out)

  150. {

  151. const flat_binder_object* flat = in.readObject(false);

  152. if (flat) {

  153. switch (flat->type) {

  154. case BINDER_TYPE_BINDER:

  155. *out = static_cast<IBinder*>(flat->cookie);

  156. return finish_unflatten_binder(NULL, *flat, in);

  157. case BINDER_TYPE_HANDLE:

  158. *out = proc->getStrongProxyForHandle(flat->handle);

  159. return finish_unflatten_binder(

  160. static_cast<BpBinder*>(out->get()), *flat, in);

  161. }

  162. }

  163. return BAD_TYPE;

  164. }

  165. status_t unflatten_binder(const sp& proc,

  166. const Parcel& in, wp* out)

  167. {

  168. const flat_binder_object* flat = in.readObject(false);

  169. if (flat) {

  170. switch (flat->type) {

  171. case BINDER_TYPE_BINDER:

  172. *out = static_cast<IBinder*>(flat->cookie);

  173. return finish_unflatten_binder(NULL, *flat, in);

  174. case BINDER_TYPE_WEAK_BINDER:

  175. if (flat->binder != NULL) {

  176. out->set_object_and_refs(

  177. static_cast<IBinder*>(flat->cookie),

  178. static_castRefBase::weakref\_type\*(flat->binder));

  179. } else {

  180. *out = NULL;

  181. }

  182. return finish_unflatten_binder(NULL, *flat, in);

  183. case BINDER_TYPE_HANDLE:

  184. case BINDER_TYPE_WEAK_HANDLE:

  185. *out = proc->getWeakProxyForHandle(flat->handle);

  186. return finish_unflatten_binder(

  187. static_cast<BpBinder*>(out->unsafe_get()), *flat, in);

  188. }

  189. }

  190. return BAD_TYPE;

  191. }

  192. // ---------------------------------------------------------------------------

  193. Parcel::Parcel()

  194. {

  195. initState();

  196. }

  197. Parcel::~Parcel()

  198. {

  199. freeDataNoInit();

  200. }

  201. const uint8_t* Parcel::data() const

  202. {

  203. return mData;

  204. }

  205. size_t Parcel::dataSize() const

  206. {

  207. return (mDataSize > mDataPos ? mDataSize : mDataPos);

  208. }

  209. size_t Parcel::dataAvail() const

  210. {

  211. // TODO: decide what to do about the possibility that this can

  212. // report an available-data size that exceeds a Java int’s max

  213. // positive value, causing havoc.  Fortunately this will only

  214. // happen if someone constructs a Parcel containing more than two

  215. // gigabytes of data, which on typical phone hardware is simply

  216. // not possible.

  217. return dataSize() - dataPosition();

  218. }

  219. size_t Parcel::dataPosition() const

  220. {

  221. return mDataPos;

  222. }

  223. size_t Parcel::dataCapacity() const

  224. {

  225. return mDataCapacity;

  226. }

  227. status_t Parcel::setDataSize(size_t size)

  228. {

  229. status_t err;

  230. err = continueWrite(size);

  231. if (err == NO_ERROR) {

  232. mDataSize = size;

  233. LOGV(“setDataSize Setting data size of %p to %d/n”, this, mDataSize);

  234. }

  235. return err;

  236. }

  237. void Parcel::setDataPosition(size_t pos) const

  238. {

  239. mDataPos = pos;

  240. mNextObjectHint = 0;

  241. }

  242. status_t Parcel::setDataCapacity(size_t size)

  243. {

  244. if (size > mDataSize) return continueWrite(size);

  245. return NO_ERROR;

  246. }

  247. status_t Parcel::setData(const uint8_t* buffer, size_t len)

  248. {

  249. status_t err = restartWrite(len);

  250. if (err == NO_ERROR) {

  251. memcpy(const_cast<uint8_t*>(data()), buffer, len);

  252. mDataSize = len;

  253. mFdsKnown = false;

  254. }

  255. return err;

  256. }

  257. status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len)

  258. {

  259. const sp proc(ProcessState::self());

  260. status_t err;

  261. uint8_t *data = parcel->mData;

  262. size_t *objects = parcel->mObjects;

  263. size_t size = parcel->mObjectsSize;

  264. int startPos = mDataPos;

  265. int firstIndex = -1, lastIndex = -2;

  266. if (len == 0) {

  267. return NO_ERROR;

  268. }

  269. // range checks against the source parcel size

  270. if ((offset > parcel->mDataSize)

  271. || (len > parcel->mDataSize)

  272. || (offset + len > parcel->mDataSize)) {

  273. return BAD_VALUE;

  274. }

  275. // Count objects in range

  276. for (int i = 0; i < (int) size; i++) {

  277. size_t off = objects[i];

  278. if ((off >= offset) && (off < offset + len)) {

  279. if (firstIndex == -1) {

  280. firstIndex = i;

  281. }

  282. lastIndex = i;

  283. }

  284. }

  285. int numObjects = lastIndex - firstIndex + 1;

  286. // grow data

  287. err = growData(len);

  288. if (err != NO_ERROR) {

  289. return err;

  290. }

  291. // append data

  292. memcpy(mData + mDataPos, data + offset, len);

  293. mDataPos += len;

  294. mDataSize += len;

  295. if (numObjects > 0) {

  296. // grow objects

  297. if (mObjectsCapacity < mObjectsSize + numObjects) {

  298. int newSize = ((mObjectsSize + numObjects)*3)/2;

  299. size_t *objects =

  300. (size_t*)realloc(mObjects, newSize*sizeof(size_t));

  301. if (objects == (size_t*)0) {

  302. return NO_MEMORY;

  303. }

  304. mObjects = objects;

  305. mObjectsCapacity = newSize;

  306. }

  307. // append and acquire objects

  308. int idx = mObjectsSize;

  309. for (int i = firstIndex; i <= lastIndex; i++) {

  310. size_t off = objects[i] - offset + startPos;

  311. mObjects[idx++] = off;

  312. mObjectsSize++;

  313. flat_binder_object* flat

  314. = reinterpret_cast<flat_binder_object*>(mData + off);

  315. acquire_object(proc, *flat, this);

  316. if (flat->type == BINDER_TYPE_FD) {

  317. // If this is a file descriptor, we need to dup it so the

  318. // new Parcel now owns its own fd, and can declare that we

  319. // officially know we have fds.

  320. flat->handle = dup(flat->handle);

  321. flat->cookie = (void*)1;

  322. mHasFds = mFdsKnown = true;

  323. }

  324. }

  325. }

  326. return NO_ERROR;

  327. }

  328. bool Parcel::hasFileDescriptors() const

  329. {

  330. if (!mFdsKnown) {

  331. scanForFds();

  332. }

  333. return mHasFds;

  334. }

  335. status_t Parcel::writeInterfaceToken(const String16& interface)

  336. {

  337. // currently the interface identification token is just its name as a string

  338. return writeString16(interface);

  339. }

  340. bool Parcel::checkInterface(IBinder* binder) const

  341. {

  342. return enforceInterface(binder->getInterfaceDescriptor());

  343. }

  344. bool Parcel::enforceInterface(const String16& interface) const

  345. {

  346. const String16 str(readString16());

  347. if (str == interface) {

  348. return true;

  349. } else {

  350. LOGW(“**** enforceInterface() expected ‘%s’ but read ‘%s’/n”,

  351. String8(interface).string(), String8(str).string());

  352. return false;

  353. }

  354. }

  355. const size_t* Parcel::objects() const

  356. {

  357. return mObjects;

  358. }

  359. size_t Parcel::objectsCount() const

  360. {

  361. return mObjectsSize;

  362. }

  363. status_t Parcel::errorCheck() const

  364. {

  365. return mError;

  366. }

  367. void Parcel::setError(status_t err)

  368. {

  369. mError = err;

  370. }

  371. status_t Parcel::finishWrite(size_t len)

  372. {

  373. //printf(“Finish write of %d/n”, len);

  374. mDataPos += len;

  375. LOGV(“finishWrite Setting data pos of %p to %d/n”, this, mDataPos);

  376. if (mDataPos > mDataSize) {

  377. mDataSize = mDataPos;

  378. LOGV(“finishWrite Setting data size of %p to %d/n”, this, mDataSize);

  379. }

  380. //printf(“New pos=%d, size=%d/n”, mDataPos, mDataSize);

  381. return NO_ERROR;

  382. }

  383. status_t Parcel::writeUnpadded(const void* data, size_t len)

  384. {

  385. size_t end = mDataPos + len;

  386. if (end < mDataPos) {

  387. // integer overflow

  388. return BAD_VALUE;

  389. }

  390. if (end <= mDataCapacity) {

  391. restart_write:

  392. memcpy(mData+mDataPos, data, len);

  393. return finishWrite(len);

  394. }

  395. status_t err = growData(len);

  396. if (err == NO_ERROR) goto restart_write;

  397. return err;

  398. }

  399. status_t Parcel::write(const void* data, size_t len)

  400. {

  401. void* const d = writeInplace(len);

  402. if (d) {

  403. memcpy(d, data, len);

  404. return NO_ERROR;

  405. }

  406. return mError;

  407. }

  408. void* Parcel::writeInplace(size_t len)

  409. {

  410. const size_t padded = PAD_SIZE(len);

  411. // sanity check for integer overflow

  412. if (mDataPos+padded < mDataPos) {

  413. return NULL;

  414. }

  415. if ((mDataPos+padded) <= mDataCapacity) {

  416. restart_write:

  417. //printf(“Writing %ld bytes, padded to %ld/n”, len, padded);

  418. uint8_t* const data = mData+mDataPos;

  419. // Need to pad at end?

  420. if (padded != len) {

  421. #if BYTE_ORDER == BIG_ENDIAN

  422. static const uint32_t mask[4] = {

  423. 0x00000000, 0xffffff00, 0xffff0000, 0xff000000

  424. };

  425. #endif

  426. #if BYTE_ORDER == LITTLE_ENDIAN

  427. static const uint32_t mask[4] = {

  428. 0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff

  429. };

  430. #endif

  431. //printf(“Applying pad mask: %p to %p/n”, (void*)mask[padded-len],

  432. //    *reinterpret_cast<void**>(data+padded-4));

  433. *reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len];

  434. }

  435. finishWrite(padded);

  436. return data;

  437. }

  438. status_t err = growData(padded);

  439. if (err == NO_ERROR) goto restart_write;

  440. return NULL;

  441. }

  442. status_t Parcel::writeInt32(int32_t val)

  443. {

  444. return writeAligned(val);

  445. }

  446. status_t Parcel::writeInt64(int64_t val)

  447. {

  448. return writeAligned(val);

  449. }

  450. status_t Parcel::writeFloat(float val)

  451. {

  452. return writeAligned(val);

  453. }

  454. status_t Parcel::writeDouble(double val)

  455. {

  456. return writeAligned(val);

  457. }

  458. status_t Parcel::writeIntPtr(intptr_t val)

  459. {

  460. return writeAligned(val);

  461. }

  462. status_t Parcel::writeCString(const char* str)

  463. {

  464. return write(str, strlen(str)+1);

  465. }

  466. status_t Parcel::writeString8(const String8& str)

  467. {

  468. status_t err = writeInt32(str.bytes());

  469. if (err == NO_ERROR) {

  470. err = write(str.string(), str.bytes()+1);

  471. }

  472. return err;

  473. }

  474. status_t Parcel::writeString16(const String16& str)

  475. {

  476. return writeString16(str.string(), str.size());

  477. }

  478. status_t Parcel::writeString16(const char16_t* str, size_t len)

  479. {

  480. if (str == NULL) return writeInt32(-1);

  481. status_t err = writeInt32(len);

  482. if (err == NO_ERROR) {

  483. len *= sizeof(char16_t);

  484. uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t));

  485. if (data) {

  486. memcpy(data, str, len);

  487. *reinterpret_cast<char16_t*>(data+len) = 0;

  488. return NO_ERROR;

  489. }

  490. err = mError;

  491. }

  492. return err;

  493. }

  494. status_t Parcel::writeStrongBinder(const sp& val)

  495. {

  496. return flatten_binder(ProcessState::self(), val, this);

  497. }

  498. status_t Parcel::writeWeakBinder(const wp& val)

  499. {

  500. return flatten_binder(ProcessState::self(), val, this);

  501. }

  502. status_t Parcel::writeNativeHandle(const native_handle* handle)

  503. {

  504. if (!handle || handle->version != sizeof(native_handle))

  505. return BAD_TYPE;

  506. status_t err;

  507. err = writeInt32(handle->numFds);

  508. if (err != NO_ERROR) return err;

  509. err = writeInt32(handle->numInts);

  510. if (err != NO_ERROR) return err;

  511. for (int i=0 ; err==NO_ERROR && inumFds ; i++)

  512. err = writeDupFileDescriptor(handle->data[i]);

  513. if (err != NO_ERROR) {

  514. LOGD(“write native handle, write dup fd failed”);

  515. return err;

  516. }

  517. err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);

  518. return err;

  519. }

  520. status_t Parcel::writeFileDescriptor(int fd)

  521. {

  522. flat_binder_object obj;

  523. obj.type = BINDER_TYPE_FD;

  524. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  525. obj.handle = fd;

  526. obj.cookie = (void*)0;

  527. return writeObject(obj, true);

  528. }

  529. status_t Parcel::writeDupFileDescriptor(int fd)

  530. {

  531. flat_binder_object obj;

  532. obj.type = BINDER_TYPE_FD;

  533. obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;

  534. obj.handle = dup(fd);

  535. obj.cookie = (void*)1;

  536. return writeObject(obj, true);

  537. }

  538. status_t Parcel::write(const Flattenable& val)

  539. {

  540. status_t err;

  541. // size if needed

  542. size_t len = val.getFlattenedSize();

  543. size_t fd_count = val.getFdCount();

  544. err = this->writeInt32(len);

  545. if (err) return err;

  546. err = this->writeInt32(fd_count);

  547. if (err) return err;

  548. // payload

  549. void* buf = this->writeInplace(PAD_SIZE(len));

  550. if (buf == NULL)

  551. return BAD_VALUE;

  552. int* fds = NULL;

  553. if (fd_count) {

  554. fds = new int[fd_count];

  555. }

  556. err = val.flatten(buf, len, fds, fd_count);

  557. for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {

  558. err = this->writeDupFileDescriptor( fds[i] );

  559. }

  560. if (fd_count) {

  561. delete [] fds;

  562. }

  563. return err;

  564. }

  565. status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)

  566. {

  567. const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;

  568. const bool enoughObjects = mObjectsSize < mObjectsCapacity;

  569. if (enoughData && enoughObjects) {

  570. restart_write:

  571. *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;

  572. // Need to write meta-data?

  573. if (nullMetaData || val.binder != NULL) {

  574. mObjects[mObjectsSize] = mDataPos;

  575. acquire_object(ProcessState::self(), val, this);

  576. mObjectsSize++;

  577. }

  578. // remember if it’s a file descriptor

  579. if (val.type == BINDER_TYPE_FD) {

  580. mHasFds = mFdsKnown = true;

  581. }

  582. return finishWrite(sizeof(flat_binder_object));

  583. }

  584. if (!enoughData) {

  585. const status_t err = growData(sizeof(val));

  586. if (err != NO_ERROR) return err;

  587. }

  588. if (!enoughObjects) {

  589. size_t newSize = ((mObjectsSize+2)*3)/2;

  590. size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t));

  591. if (objects == NULL) return NO_MEMORY;

  592. mObjects = objects;

  593. mObjectsCapacity = newSize;

  594. }

  595. goto restart_write;

  596. }

  597. void Parcel::remove(size_t start, size_t amt)

  598. {

  599. LOG_ALWAYS_FATAL(“Parcel::remove() not yet implemented!”);

  600. }

  601. status_t Parcel::read(void* outData, size_t len) const

  602. {

  603. if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {

  604. memcpy(outData, mData+mDataPos, len);

  605. mDataPos += PAD_SIZE(len);

  606. LOGV(“read Setting data pos of %p to %d/n”, this, mDataPos);

  607. return NO_ERROR;

  608. }

  609. return NOT_ENOUGH_DATA;

  610. }

  611. const void* Parcel::readInplace(size_t len) const

  612. {

  613. if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) {

  614. const void* data = mData+mDataPos;

  615. mDataPos += PAD_SIZE(len);

  616. LOGV(“readInplace Setting data pos of %p to %d/n”, this, mDataPos);

  617. return data;

  618. }

  619. return NULL;

  620. }

  621. template

  622. status_t Parcel::readAligned(T *pArg) const {

  623. COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));

  624. if ((mDataPos+sizeof(T)) <= mDataSize) {

  625. const void* data = mData+mDataPos;

  626. mDataPos += sizeof(T);

  627. *pArg =  *reinterpret_cast<const T*>(data);

  628. return NO_ERROR;

  629. } else {

  630. return NOT_ENOUGH_DATA;

  631. }

  632. }

  633. template

  634. T Parcel::readAligned() const {

  635. T result;

  636. if (readAligned(&result) != NO_ERROR) {

  637. result = 0;

  638. }

  639. return result;

  640. }

  641. template

  642. status_t Parcel::writeAligned(T val) {

  643. COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));

  644. if ((mDataPos+sizeof(val)) <= mDataCapacity) {

  645. restart_write:

  646. *reinterpret_cast<T*>(mData+mDataPos) = val;

  647. return finishWrite(sizeof(val));

  648. }

  649. status_t err = growData(sizeof(val));

  650. if (err == NO_ERROR) goto restart_write;

  651. return err;

  652. }

  653. status_t Parcel::readInt32(int32_t *pArg) const

  654. {

  655. return readAligned(pArg);

  656. }

  657. int32_t Parcel::readInt32() const

  658. {

  659. return readAligned<int32_t>();

  660. }

  661. status_t Parcel::readInt64(int64_t *pArg) const

  662. {

  663. return readAligned(pArg);

  664. }

  665. int64_t Parcel::readInt64() const

  666. {

  667. return readAligned<int64_t>();

  668. }

  669. status_t Parcel::readFloat(float *pArg) const

  670. {

  671. return readAligned(pArg);

  672. }

  673. float Parcel::readFloat() const

  674. {

  675. return readAligned<float>();

  676. }

  677. status_t Parcel::readDouble(double *pArg) const

  678. {

  679. return readAligned(pArg);

  680. }

  681. double Parcel::readDouble() const

  682. {

  683. return readAligned<double>();

  684. }

  685. status_t Parcel::readIntPtr(intptr_t *pArg) const

  686. {

  687. return readAligned(pArg);

  688. }

  689. intptr_t Parcel::readIntPtr() const

  690. {

  691. return readAligned<intptr_t>();

  692. }

  693. const char* Parcel::readCString() const

  694. {

  695. const size_t avail = mDataSize-mDataPos;

  696. if (avail > 0) {

  697. const char* str = reinterpret_cast<const char*>(mData+mDataPos);

  698. // is the string’s trailing NUL within the parcel’s valid bounds?

  699. const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));

  700. if (eos) {

  701. const size_t len = eos - str;

  702. mDataPos += PAD_SIZE(len+1);

  703. LOGV(“readCString Setting data pos of %p to %d/n”, this, mDataPos);

  704. return str;

  705. }

  706. }

  707. return NULL;

  708. }

  709. String8 Parcel::readString8() const

  710. {

  711. int32_t size = readInt32();

  712. // watch for potential int overflow adding 1 for trailing NUL

  713. if (size > 0 && size < INT32_MAX) {

  714. const char* str = (const char*)readInplace(size+1);

  715. if (str) return String8(str, size);

  716. }

  717. return String8();

  718. }

  719. String16 Parcel::readString16() const

  720. {

  721. size_t len;

  722. const char16_t* str = readString16Inplace(&len);

  723. if (str) return String16(str, len);

  724. LOGE(“Reading a NULL string not supported here.”);

  725. return String16();

  726. }

  727. const char16_t* Parcel::readString16Inplace(size_t* outLen) const

  728. {

  729. int32_t size = readInt32();

  730. // watch for potential int overflow from size+1

  731. if (size >= 0 && size < INT32_MAX) {

  732. *outLen = size;

  733. const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));

  734. if (str != NULL) {

  735. return str;

  736. }

  737. }

  738. *outLen = 0;

  739. return NULL;

  740. }

  741. sp Parcel::readStrongBinder() const

  742. {

  743. sp val;

  744. unflatten_binder(ProcessState::self(), *this, &val);

  745. return val;

  746. }

  747. wp Parcel::readWeakBinder() const

  748. {

  749. wp val;

  750. unflatten_binder(ProcessState::self(), *this, &val);

  751. return val;

  752. }

  753. native_handle* Parcel::readNativeHandle() const

  754. {

  755. int numFds, numInts;

  756. status_t err;

  757. err = readInt32(&numFds);

  758. if (err != NO_ERROR) return 0;

  759. err = readInt32(&numInts);

  760. if (err != NO_ERROR) return 0;

  761. native_handle* h = native_handle_create(numFds, numInts);

  762. for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {

  763. h->data[i] = dup(readFileDescriptor());

  764. if (h->data[i] < 0) err = BAD_VALUE;

  765. }

  766. err = read(h->data + numFds, sizeof(int)*numInts);

  767. if (err != NO_ERROR) {

  768. native_handle_close(h);

  769. native_handle_delete(h);

  770. h = 0;

  771. }

  772. return h;

  773. }

  774. int Parcel::readFileDescriptor() const

  775. {

  776. const flat_binder_object* flat = readObject(true);

  777. if (flat) {

  778. switch (flat->type) {

  779. case BINDER_TYPE_FD:

  780. //LOGI(“Returning file descriptor %ld from parcel %p/n”, flat->handle, this);

  781. return flat->handle;

  782. }

  783. }

  784. return BAD_TYPE;

  785. }

  786. status_t Parcel::read(Flattenable& val) const

  787. {

  788. // size

  789. const size_t len = this->readInt32();

  790. const size_t fd_count = this->readInt32();

  791. // payload

  792. void const* buf = this->readInplace(PAD_SIZE(len));

  793. if (buf == NULL)

  794. return BAD_VALUE;

  795. int* fds = NULL;

  796. if (fd_count) {

  797. fds = new int[fd_count];

  798. }

  799. status_t err = NO_ERROR;

  800. for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {

  801. fds[i] = dup(this->readFileDescriptor());

  802. if (fds[i] < 0) err = BAD_VALUE;

  803. }

  804. if (err == NO_ERROR) {

  805. err = val.unflatten(buf, len, fds, fd_count);

  806. }

  807. if (fd_count) {

  808. delete [] fds;

  809. }

  810. return err;

  811. }

  812. const flat_binder_object* Parcel::readObject(bool nullMetaData) const

  813. {

  814. const size_t DPOS = mDataPos;

  815. if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) {

  816. const flat_binder_object* obj

  817. = reinterpret_cast<const flat_binder_object*>(mData+DPOS);

  818. mDataPos = DPOS + sizeof(flat_binder_object);

  819. if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) {

  820. // When transferring a NULL object, we don’t write it into

  821. // the object list, so we don’t want to check for it when

  822. // reading.

  823. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  824. return obj;

  825. }

  826. // Ensure that this object is valid…

  827. size_t* const OBJS = mObjects;

  828. const size_t N = mObjectsSize;

  829. size_t opos = mNextObjectHint;

  830. if (N > 0) {

  831. LOGV(“Parcel %p looking for obj at %d, hint=%d/n”,

  832. this, DPOS, opos);

  833. // Start at the current hint position, looking for an object at

  834. // the current data position.

  835. if (opos < N) {

  836. while (opos < (N-1) && OBJS[opos] < DPOS) {

  837. opos++;

  838. }

  839. } else {

  840. opos = N-1;

  841. }

  842. if (OBJS[opos] == DPOS) {

  843. // Found it!

  844. LOGV(“Parcel found obj %d at index %d with forward search”,

  845. this, DPOS, opos);

  846. mNextObjectHint = opos+1;

  847. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  848. return obj;

  849. }

  850. // Look backwards for it…

  851. while (opos > 0 && OBJS[opos] > DPOS) {

  852. opos–;

  853. }

  854. if (OBJS[opos] == DPOS) {

  855. // Found it!

  856. LOGV(“Parcel found obj %d at index %d with backward search”,

  857. this, DPOS, opos);

  858. mNextObjectHint = opos+1;

  859. LOGV(“readObject Setting data pos of %p to %d/n”, this, mDataPos);

  860. return obj;

  861. }

  862. }

  863. LOGW(“Attempt to read object from Parcel %p at offset %d that is not in the object list”,

  864. this, DPOS);

  865. }

  866. return NULL;

  867. }

  868. void Parcel::closeFileDescriptors()

  869. {

  870. size_t i = mObjectsSize;

  871. if (i > 0) {

  872. //LOGI(“Closing file descriptors for %d objects…”, mObjectsSize);

  873. }

  874. while (i > 0) {

  875. i–;

  876. const flat_binder_object* flat

  877. = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);

  878. if (flat->type == BINDER_TYPE_FD) {

  879. //LOGI(“Closing fd: %ld/n”, flat->handle);

  880. close(flat->handle);

  881. }

  882. }

  883. }

  884. const uint8_t* Parcel::ipcData() const

  885. {

  886. return mData;

  887. }

  888. size_t Parcel::ipcDataSize() const

  889. {

  890. return (mDataSize > mDataPos ? mDataSize : mDataPos);

  891. }

  892. const size_t* Parcel::ipcObjects() const

  893. {

  894. return mObjects;

  895. }

  896. size_t Parcel::ipcObjectsCount() const

  897. {

  898. return mObjectsSize;

  899. }

  900. void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize,

  901. const size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie)

  902. {

  903. freeDataNoInit();

  904. mError = NO_ERROR;

  905. mData = const_cast<uint8_t*>(data);

  906. mDataSize = mDataCapacity = dataSize;

  907. //LOGI(“setDataReference Setting data size of %p to %lu (pid=%d)/n”, this, mDataSize, getpid());

  908. mDataPos = 0;

  909. LOGV(“setDataReference Setting data pos of %p to %d/n”, this, mDataPos);

  910. mObjects = const_cast<size_t*>(objects);

  911. mObjectsSize = mObjectsCapacity = objectsCount;

  912. mNextObjectHint = 0;

  913. mOwner = relFunc;

  914. mOwnerCookie = relCookie;

  915. scanForFds();

  916. }

  917. void Parcel::print(TextOutput& to, uint32_t flags) const

  918. {

  919. to << “Parcel(”;

  920. if (errorCheck() != NO_ERROR) {

  921. const status_t err = errorCheck();

  922. to << “Error: " << (void*)err << " /”" << strerror(-err) << “/”";

  923. } else if (dataSize() > 0) {

  924. const uint8_t* DATA = data();

  925. to << indent << HexDump(DATA, dataSize()) << dedent;

  926. const size_t* OBJS = objects();

  927. const size_t N = objectsCount();

  928. for (size_t i=0; i<N; i++) {

  929. const flat_binder_object* flat

  930. = reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]);

  931. to << endl << “Object #” << i << " @ " << (void*)OBJS[i] << ": "

  932. << TypeCode(flat->type & 0x7f7f7f00)

  933. << " = " << flat->binder;

  934. }

  935. } else {

  936. to << “NULL”;

  937. }

  938. to << “)”;

  939. }

  940. void Parcel::releaseObjects()

  941. {

  942. const sp proc(ProcessState::self());

  943. size_t i = mObjectsSize;

  944. uint8_t* const data = mData;

  945. size_t* const objects = mObjects;

  946. while (i > 0) {

  947. i–;

  948. const flat_binder_object* flat

  949. = reinterpret_cast<flat_binder_object*>(data+objects[i]);

  950. release_object(proc, *flat, this);

  951. }

  952. }

  953. void Parcel::acquireObjects()

  954. {

  955. const sp proc(ProcessState::self());

  956. size_t i = mObjectsSize;

  957. uint8_t* const data = mData;

  958. size_t* const objects = mObjects;

  959. while (i > 0) {

  960. i–;

  961. const flat_binder_object* flat

  962. = reinterpret_cast<flat_binder_object*>(data+objects[i]);

  963. acquire_object(proc, *flat, this);

  964. }

  965. }

  966. void Parcel::freeData()

  967. {

  968. freeDataNoInit();

  969. initState();

  970. }

  971. void Parcel::freeDataNoInit()

  972. {

  973. if (mOwner) {

  974. //LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());

  975. mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);

  976. } else {

  977. releaseObjects();

  978. if (mData) free(mData);

  979. if (mObjects) free(mObjects);

  980. }

  981. }

  982. status_t Parcel::growData(size_t len)

  983. {

  984. size_t newSize = ((mDataSize+len)*3)/2;

  985. return (newSize <= mDataSize)

  986. ? (status_t) NO_MEMORY

  987. : continueWrite(newSize);

  988. }

  989. status_t Parcel::restartWrite(size_t desired)

  990. {

  991. if (mOwner) {

  992. freeData();

  993. return continueWrite(desired);

  994. }

  995. uint8_t* data = (uint8_t*)realloc(mData, desired);

  996. if (!data && desired > mDataCapacity) {

  997. mError = NO_MEMORY;

  998. return NO_MEMORY;

  999. }

  1000. releaseObjects();

  1001. if (data) {

  1002. mData = data;

  1003. mDataCapacity = desired;

  1004. }

  1005. mDataSize = mDataPos = 0;

  1006. LOGV(“restartWrite Setting data size of %p to %d/n”, this, mDataSize);

  1007. LOGV(“restartWrite Setting data pos of %p to %d/n”, this, mDataPos);

  1008. free(mObjects);

  1009. mObjects = NULL;

  1010. mObjectsSize = mObjectsCapacity = 0;

  1011. mNextObjectHint = 0;

  1012. mHasFds = false;

  1013. mFdsKnown = true;

  1014. return NO_ERROR;

  1015. }

  1016. status_t Parcel::continueWrite(size_t desired)

  1017. {

  1018. // If shrinking, first adjust for any objects that appear

  1019. // after the new data size.

  1020. size_t objectsSize = mObjectsSize;

  1021. if (desired < mDataSize) {

  1022. if (desired == 0) {

  1023. objectsSize = 0;

  1024. } else {

  1025. while (objectsSize > 0) {

  1026. if (mObjects[objectsSize-1] < desired)

  1027. break;

  1028. objectsSize–;

  1029. }

  1030. }

  1031. }

  1032. if (mOwner) {

  1033. // If the size is going to zero, just release the owner’s data.

  1034. if (desired == 0) {

  1035. freeData();

  1036. return NO_ERROR;

  1037. }

  1038. // If there is a different owner, we need to take

  1039. // posession.

  1040. uint8_t* data = (uint8_t*)malloc(desired);

  1041. if (!data) {

  1042. mError = NO_MEMORY;

  1043. return NO_MEMORY;

  1044. }

  1045. size_t* objects = NULL;

  1046. if (objectsSize) {

  1047. objects = (size_t*)malloc(objectsSize*sizeof(size_t));

  1048. if (!objects) {

  1049. mError = NO_MEMORY;

  1050. return NO_MEMORY;

  1051. }

  1052. // Little hack to only acquire references on objects

  1053. // we will be keeping.

  1054. size_t oldObjectsSize = mObjectsSize;

  1055. mObjectsSize = objectsSize;

  1056. acquireObjects();

  1057. mObjectsSize = oldObjectsSize;

  1058. }

  1059. if (mData) {

  1060. memcpy(data, mData, mDataSize < desired ? mDataSize : desired);

  1061. }

  1062. if (objects && mObjects) {

  1063. memcpy(objects, mObjects, objectsSize*sizeof(size_t));

  1064. }

  1065. //LOGI(“Freeing data ref of %p (pid=%d)/n”, this, getpid());

  1066. mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie);

  1067. mOwner = NULL;

  1068. mData = data;

  1069. mObjects = objects;

  1070. mDataSize = (mDataSize < desired) ? mDataSize : desired;

  1071. LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  1072. mDataCapacity = desired;

  1073. mObjectsSize = mObjectsCapacity = objectsSize;

  1074. mNextObjectHint = 0;

  1075. } else if (mData) {

  1076. if (objectsSize < mObjectsSize) {

  1077. // Need to release refs on any objects we are dropping.

  1078. const sp proc(ProcessState::self());

  1079. for (size_t i=objectsSize; i<mObjectsSize; i++) {

  1080. const flat_binder_object* flat

  1081. = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]);

  1082. if (flat->type == BINDER_TYPE_FD) {

  1083. // will need to rescan because we may have lopped off the only FDs

  1084. mFdsKnown = false;

  1085. }

  1086. release_object(proc, *flat, this);

  1087. }

  1088. size_t* objects =

  1089. (size_t*)realloc(mObjects, objectsSize*sizeof(size_t));

  1090. if (objects) {

  1091. mObjects = objects;

  1092. }

  1093. mObjectsSize = objectsSize;

  1094. mNextObjectHint = 0;

  1095. }

  1096. // We own the data, so we can just do a realloc().

  1097. if (desired > mDataCapacity) {

  1098. uint8_t* data = (uint8_t*)realloc(mData, desired);

  1099. if (data) {

  1100. mData = data;

  1101. mDataCapacity = desired;

  1102. } else if (desired > mDataCapacity) {

  1103. mError = NO_MEMORY;

  1104. return NO_MEMORY;

  1105. }

  1106. } else {

  1107. mDataSize = desired;

  1108. LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  1109. if (mDataPos > desired) {

  1110. mDataPos = desired;

  1111. LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);

  1112. }

  1113. }

  1114. } else {

  1115. // This is the first data.  Easy!

  1116. uint8_t* data = (uint8_t*)malloc(desired);

  1117. if (!data) {

  1118. mError = NO_MEMORY;

  1119. return NO_MEMORY;

  1120. }

  1121. if(!(mDataCapacity == 0 && mObjects == NULL

  1122. && mObjectsCapacity == 0)) {

  1123. LOGE(“continueWrite: %d/%p/%d/%d”, mDataCapacity, mObjects, mObjectsCapacity, desired);

  1124. }

  1125. mData = data;

  1126. mDataSize = mDataPos = 0;

1
363.         LOGV(“continueWrite Setting data size of %p to %d/n”, this, mDataSize);

  1. LOGV(“continueWrite Setting data pos of %p to %d/n”, this, mDataPos);

  2. mDataCapacity = desired;

  3. }

  4. return NO_ERROR;

  5. }

  6. void Parcel::initState()

  7. {

  8. mError = NO_ERROR;

  9. mData = 0;

  10. mDataSize = 0;

  11. mDataCapacity = 0;

  12. mDataPos = 0;

  13. LOGV(“initState Setting data size of %p to %d/n”, this, mDataSize);

  14. LOGV(“initState Setting data pos of %p to %d/n”, this, mDataPos);

  15. mObjects = NULL;

  16. mObjectsSize = 0;

  17. mObjectsCapacity = 0;

  18. mNextObjectHint = 0;

  19. mHasFds = false;

  20. mFdsKnown = true;

  21. mOwner = NULL;

  22. }

  23. void Parcel::scanForFds() const

  24. {

  25. bool hasFds = false;

  26. for (size_t i=0; i<mObjectsSize; i++) {

  27. const flat_binder_object* flat

  28. = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]);

  29. if (flat->type == BINDER_TYPE_FD) {

  30. hasFds = true;

  31. break;

  32. }

  33. }

  34. mHasFds = hasFds;

  35. mFdsKnown = true;

  36. }

  37. }; // namespace android

本文的源码使用的是Android 2.1版本。

上一篇中我们透过源码看到了Parcel背后的机制,本质上把它当成一个Serialize就可以了,只是它是在内存中完成的序列化和反序列化,利用的是连续的内存空间,因此会更加高效。

我们接下来要说的是Parcel类如何应用。就应用程序而言,最常见使用Parcel类的场景就是在Activity间传递数据。没错,在Activity间使用Intent传递数据的时候,可以通过Parcelable机制传递复杂的对象。

在下面的程序中,MyColor用于保存一个颜色值,MainActivity在用户点击屏幕时将MyColor对象设成红色,传递到SubActivity中,此时SubActivity的TextView显示为红色的背景;当点击SubActivity时,将颜色值改为绿色,返回MainActivity,期望的是MainActivity的TextView显示绿色背景。

来看一下MyColor类的实现代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.graphics.Color;

  3. import android.os.Parcel;

  4. import android.os.Parcelable;

  5. /**

  6. * @author 曹文斌

  7. * http://blog.csdn.net/caowenbin

  8. *

  9. */

  10. public class MyColor implements Parcelable {

  11. private int color=Color.BLACK;

  12. MyColor(){

  13. color=Color.BLACK;

  14. }

  15. MyColor(Parcel in){

  16. color=in.readInt();

  17. }

  18. public int getColor(){

  19. return color;

  20. }

  21. public void setColor(int color){

  22. this.color=color;

  23. }

  24. @Override

  25. public int describeContents() {

  26. return 0;

  27. }

  28. @Override

  29. public void writeToParcel(Parcel dest, int flags) {

  30. dest.writeInt(color);

  31. }

  32. public static final Parcelable.Creator CREATOR

  33. = new Parcelable.Creator() {

  34. public MyColor createFromParcel(Parcel in) {

  35. return new MyColor(in);

  36. }

  37. public MyColor[] newArray(int size) {

  38. return new MyColor[size];

  39. }

  40. };

  41. }

该类实现了Parcelable接口,提供了默认的构造函数,同时也提供了可从Parcel对象开始的构造函数,另外还实现了一个static的构造器用于构造对象和数组。代码很简单,不一一解释了。

再看MainActivity的代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.app.Activity;

  3. import android.content.Intent;

  4. import android.graphics.Color;

  5. import android.os.Bundle;

  6. import android.view.MotionEvent;

  7. /**

  8. * @author 曹文斌

  9. * http://blog.csdn.net/caowenbin

  10. *

  11. */

  12. public class MainActivity extends Activity {

  13. private final int SUB_ACTIVITY=0;

  14. private MyColor color=new MyColor();

  15. @Override

  16. public void onCreate(Bundle savedInstanceState) {

  17. super.onCreate(savedInstanceState);

  18. setContentView(R.layout.main);

  19. }

  20. @Override

  21. protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  22. super.onActivityResult(requestCode, resultCode, data);

  23. if (requestCode==SUB_ACTIVITY){

  24. if (resultCode==RESULT_OK){

  25. if (data.hasExtra(“MyColor”)){

  26. color=data.getParcelableExtra(“MyColor”);  //Notice

  27. findViewById(R.id.text).setBackgroundColor(color.getColor());

  28. }

  29. }

  30. }

  31. }

  32. @Override

  33. public boolean onTouchEvent(MotionEvent event){

  34. if (event.getAction()==MotionEvent.ACTION_UP){

  35. Intent intent=new Intent();

  36. intent.setClass(this, SubActivity.class);

  37. color.setColor(Color.RED);

  38. intent.putExtra(“MyColor”, color);

  39. startActivityForResult(intent,SUB_ACTIVITY);

  40. }

  41. return super.onTouchEvent(event);

  42. }

  43. }

下面是SubActivity的代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.app.Activity;

  3. import android.content.Intent;

  4. import android.graphics.Color;

  5. import android.os.Bundle;

  6. import android.view.MotionEvent;

  7. import android.widget.TextView;

  8. /**

  9. * @author 曹文斌

  10. * http://blog.csdn.net/caowenbin

  11. *

  12. */

  13. public class SubActivity extends Activity {

  14. private MyColor color;

  15. @Override

  16. public void onCreate(Bundle savedInstanceState) {

  17. super.onCreate(savedInstanceState);

  18. setContentView(R.layout.main);

  19. ((TextView)findViewById(R.id.text)).setText(“SubActivity”);

  20. Intent intent=getIntent();

  21. if (intent!=null){

  22. if (intent.hasExtra(“MyColor”)){

  23. color=intent.getParcelableExtra(“MyColor”);

  24. findViewById(R.id.text).setBackgroundColor(color.getColor());

  25. }

  26. }

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

  1. @Override

  2. public void onCreate(Bundle savedInstanceState) {

  3. super.onCreate(savedInstanceState);

  4. setContentView(R.layout.main);

  5. }

  6. @Override

  7. protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  8. super.onActivityResult(requestCode, resultCode, data);

  9. if (requestCode==SUB_ACTIVITY){

  10. if (resultCode==RESULT_OK){

  11. if (data.hasExtra(“MyColor”)){

  12. color=data.getParcelableExtra(“MyColor”);  //Notice

  13. findViewById(R.id.text).setBackgroundColor(color.getColor());

  14. }

  15. }

  16. }

  17. }

  18. @Override

  19. public boolean onTouchEvent(MotionEvent event){

  20. if (event.getAction()==MotionEvent.ACTION_UP){

  21. Intent intent=new Intent();

  22. intent.setClass(this, SubActivity.class);

  23. color.setColor(Color.RED);

  24. intent.putExtra(“MyColor”, color);

  25. startActivityForResult(intent,SUB_ACTIVITY);

  26. }

  27. return super.onTouchEvent(event);

  28. }

  29. }

下面是SubActivity的代码:

[java]  view plain copy

  1. package com.wenbin.test;

  2. import android.app.Activity;

  3. import android.content.Intent;

  4. import android.graphics.Color;

  5. import android.os.Bundle;

  6. import android.view.MotionEvent;

  7. import android.widget.TextView;

  8. /**

  9. * @author 曹文斌

  10. * http://blog.csdn.net/caowenbin

  11. *

  12. */

  13. public class SubActivity extends Activity {

  14. private MyColor color;

  15. @Override

  16. public void onCreate(Bundle savedInstanceState) {

  17. super.onCreate(savedInstanceState);

  18. setContentView(R.layout.main);

  19. ((TextView)findViewById(R.id.text)).setText(“SubActivity”);

  20. Intent intent=getIntent();

  21. if (intent!=null){

  22. if (intent.hasExtra(“MyColor”)){

  23. color=intent.getParcelableExtra(“MyColor”);

  24. findViewById(R.id.text).setBackgroundColor(color.getColor());

  25. }

  26. }

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-guMKWa47-1718985422921)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值