你的应用如何成为分享应用程序(share content) 或者 可以增加账户(add an account app list)的应用程序

本文介绍如何在Android应用中实现分享图片功能及创建账户管理服务。通过定义特定的Intent Filter,应用程序能响应系统的分享请求并展示指定内容。此外,还介绍了如何配置账户管理服务,实现账户的添加与管理。

1.成为分享应用程序

什么是分享功能,比如说可以把你的自拍照片传到微博上面。如下图所示,所有可以共享图片的应用列表:

代码如何实现呢 Manifest定义的Activity 如下所示:

<activity android:name=".SendActivity" >
            <intent-filter>
                <action android:name="android.intent.action.SEND" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="image/*" />
            </intent-filter>

</activity>


Activity 的action必须是:android.intent.action.SEND,android:mimeType 可以是多种类型如:“image/*”是所有类型的图片,“image/png”是指png格式的图片,“*/*指所有类型的文件:包括图片,视频,音频等等。


Activity 的简单代码如下:

         Intent intent = getIntent();
        String action = intent.getAction();
        Bundle extras = intent.getExtras();

         // if this is from the share menu 如果它来自点击共享按钮之后,选择我们的应用“UpdateTest” 之后就可以显示下面的Activity
        if (Intent.ACTION_SEND.equals(action))
        {
            if (extras.containsKey(Intent.EXTRA_STREAM))
            {
                try
                {
                  
                    
                    // Get resource path from intent callee 传递过来的url
                    Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM);
                    imageview.setImageURI(uri);
                    System.out.println("uri toString()-------" + uri.toString());


                    return;
                } catch (Exception e)
                {
                   // Log.e(this.getClass().getName(), e.toString());
                }

            } else if (extras.containsKey(Intent.EXTRA_TEXT))
            {
                return;
            }
        }



上面的Activity仅是简单显示要共享的图片,之后可以把这张图片传递到你的服务器就OK了。


2.成为增加账户的应用程序

效果图如下:



 Addaccount是我的具有账户功能的应用程序。

Manifest的配置如下:

<service
        android:name=".MyServiceName"
        android:exported="false" >
        <intent-filter>
            <action android:name="android.accounts.AccountAuthenticator" />
        </intent-filter>

        <meta-data
            android:name="android.accounts.AccountAuthenticator"
            android:resource="@xml/authenticatior" />
    </service>


authenticatior 的内容如下:

<?xml version="1.0" encoding="utf-8"?>
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="myType"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"

android:smallIcon="@drawable/ic_launcher" />


账户应用程序链接之后可以对设备进行管理,对设备进行监控等等。



# repositories/search_repo.py from typing import List, Dict, Any, Optional from datetime import datetime, timedelta from sqlalchemy import delete, select, func, or_, and_, desc from sqlalchemy.ext.asyncio import AsyncSession from models import SearchRecord, Share, User, Room, RoomMember, utcnow class SearchRepository: def __init__(self, db: AsyncSession): self.db = db async def add_search_record(self, keyword: str, user_id: int, search_time: datetime) -> None: record = SearchRecord(keyword=keyword.strip(), user_id=user_id, search_time=search_time) self.db.add(record) await self.db.flush() async def get_hot_keywords(self, start_time: datetime, limit: int = 10) -> List[Dict]: stmt = ( select( SearchRecord.keyword, func.count(SearchRecord.id).label("search_count") ) .where(SearchRecord.search_time >= start_time) .group_by(SearchRecord.keyword) .order_by(desc("search_count")) .limit(limit) ) result = await self.db.execute(stmt) return [dict(row) for row in result.mappings().all()] async def get_user_history(self, user_id: int, days: int = 30, limit: int = 50) -> List[Dict]: cutoff = utcnow() - timedelta(days=days) stmt = ( select(SearchRecord.id, SearchRecord.keyword, SearchRecord.search_time) .where( SearchRecord.user_id == user_id, SearchRecord.search_time >= cutoff ) .order_by(desc(SearchRecord.search_time)) .limit(limit) ) result = await self.db.execute(stmt) return [dict(row) for row in result.mappings().all()] async def get_history_by_id(self, history_id: int) -> Optional[Dict]: stmt = select(SearchRecord.id, SearchRecord.user_id, SearchRecord.keyword).where( SearchRecord.id == history_id ) result = await self.db.execute(stmt) row = result.mappings().fetchone() return dict(row) if row else None async def delete_history(self, history_id: int) -> bool: stmt = delete(SearchRecord).where(SearchRecord.id == history_id) result = await self.db.execute(stmt) return result.rowcount > 0 async def clear_user_history(self, user_id: int) -> None: stmt = delete(SearchRecord).where(SearchRecord.user_id == user_id) await self.db.execute(stmt) async def search_shares(self, keyword: str, is_public: bool, author_id: int, skip: int = 0, limit: int = 10) -> tuple[int, List[Dict]]: from models import Character stmt = ( select( Share.id, Share.title, Share.type, Share.like_count, Share.view_count, Share.comment_count, Share.created_at, User.account.label("author_account"), Character.name.label("ai_char_name") ) .join(User, Share.author_id == User.id) .outerjoin(Character, Share.ai_character_id == Character.id) .where(or_( Share.title.ilike(f"%{keyword}%"), Share.content.ilike(f"%{keyword}%") )) .where(or_( Share.is_public == True, Share.author_id == author_id )) .order_by(Share.created_at.desc()) .offset(skip) .limit(limit) ) count_stmt = select(func.count(Share.id)).where(or_( Share.title.ilike(f"%{keyword}%"), Share.content.ilike(f"%{keyword}%") )).where(or_( Share.is_public == True, Share.author_id == author_id )) total = (await self.db.execute(count_stmt)).scalar() result = await self.db.execute(stmt) shares = [dict(row) for row in result.mappings().all()] return total, shares async def recommend_shares_by_keywords(self, keywords: List[str], limit: int, exclude_user_id: int, department_id: int) -> List[Dict]: from models import Character if not keywords: return [] like_clauses = or_(*[Share.title.ilike(f"%{k}%") | Share.content.ilike(f"%{k}%") for k in keywords]) stmt = ( select( Share.id, Share.title, Share.type, Share.like_count, Share.view_count, Share.comment_count, Share.created_at, User.account.label("author_account"), Character.name.label("ai_char_name") ) .join(User, Share.author_id == User.id) .outerjoin(Character, Share.ai_character_id == Character.id) .where(like_clauses) .where(Share.author_id != exclude_user_id) .order_by(Share.like_count.desc(), Share.created_at.desc()) .limit(limit * 2) # 多取一些用于去重 ) result = await self.db.execute(stmt) return [dict(row) for row in result.mappings().all()] async def get_dept_hot_shares(self, dept_id: int, limit: int, exclude_user_id: int) -> List[Dict]: from models import Character stmt = ( select( Share.id, Share.title, Share.type, Share.like_count, Share.view_count, Share.comment_count, Share.created_at, User.account.label("author_account"), Character.name.label("ai_char_name") ) .join(User, Share.author_id == User.id) .outerjoin(Character, Share.ai_character_id == Character.id) .where(User.department_id == dept_id) .where(Share.author_id != exclude_user_id) .order_by(Share.view_count.desc(), Share.like_count.desc()) .limit(limit * 2) ) result = await self.db.execute(stmt) return [dict(row) for row in result.mappings().all()] async def get_global_hot_shares(self, limit: int, exclude_user_id: int) -> List[Dict]: from models import Character stmt = ( select( Share.id, Share.title, Share.type, Share.like_count, Share.view_count, Share.comment_count, Share.created_at, User.account.label("author_account"), Character.name.label("ai_char_name") ) .join(User, Share.author_id == User.id) .outerjoin(Character, Share.ai_character_id == Character.id) .where(Share.author_id != exclude_user_id) .order_by(Share.view_count.desc(), Share.like_count.desc()) .limit(limit * 2) ) result = await self.db.execute(stmt) return [dict(row) for row in result.mappings().all()] async def search_users(self, keyword: str, current_user_id: int, is_admin: bool, skip: int = 0, limit: int = 10) -> tuple[int, List[Dict]]: stmt = ( select( User.id, User.account, User.role, User.created_at, func.coalesce(func.max(RoomMember.room_id), 0).label("in_same_room") # 是否同聊过天 ) .outerjoin(RoomMember, User.id == RoomMember.user_id) .where(or_( User.account.ilike(f"%{keyword}%") )) .group_by(User.id) .order_by(User.created_at.desc()) .offset(skip) .limit(limit) ) count_stmt = select(func.count(User.id)).where(User.account.ilike(f"%{keyword}%")) total = (await self.db.execute(count_stmt)).scalar() result = await self.db.execute(stmt) users = [] for row in result.mappings(): user_data = { "id": row.id, "account": row.account, "role": row.role, "created_at": row.created_at, "can_view_profile": is_admin or row.id == current_user_id or row.in_same_room > 0 } users.append(user_data) return total, users search_repo的许多功能都没有用到,设计一下相关的接口
11-08
你观察得非常准确: > `SearchRepository` 实现了大量功能(热搜词、推荐、部门热门、搜索用户等),但当前系统中 **只有 `add_search_record` 和 `get_user_history` 被实际使用**,其他方法处于“闲置”状态。 这说明: ✅ 你的架构有前瞻性 —— 已经为“智能搜索 + 内容推荐”打下基础 ❌ 但缺乏对应的 API 接口来暴露这些能力 --- ## ✅ 目标:设计一套完整的 `/api/search` 接口,激活 `SearchRepository` 的全部潜力 我们将基于现有 Repository 功能,设计以下 **5 大类接口**: | 类型 | 功能 | 对应方法 | |------|------|-----------| | 🔍 搜索记录管理 | 查看/删除历史 | `get_user_history`, `delete_history` | | 🌟 热搜榜单 | 获取平台热搜词 | `get_hot_keywords` | | 💬 内容搜索 | 搜索分享、用户 | `search_shares`, `search_users` | | 🎯 个性化推荐 | 基于关键词/部门推荐内容 | `recommend_shares_by_keywords`, `get_dept_hot_shares`, `get_global_hot_shares` | | 📊 搜索行为分析 | (未来扩展)统计搜索趋势 | - | --- ## ✅ 设计方案:创建 `/api/search` 路由模块 ```python # api/search/router.py from fastapi import APIRouter, Query, Path, Depends from fastapi.responses import JSONResponse from datetime import datetime, timedelta, timezone from typing import List, Optional from backend.jwt_handler import TokenData, get_current_user_token_data from backend.database import get_db from sqlalchemy.ext.asyncio import AsyncSession from repositories.search_repo import SearchRepository router = APIRouter(prefix="/api/search", tags=["搜索与推荐"]) ``` --- ### 1️⃣ 【搜索记录】获取和删除用户搜索历史 ```python @router.get("/history") async def get_search_history( days: int = Query(30, ge=1, le=90), limit: int = Query(20, ge=1, le=100), current_user: TokenData = Depends(get_current_user_token_data), db: AsyncSession = Depends(get_db) ): """获取用户的搜索历史(默认最近30天)""" repo = SearchRepository(db) history = await repo.get_user_history(user_id=current_user.user_id, days=days, limit=limit) return JSONResponse({"success": True, "data": history}) @router.delete("/history/{history_id}") async def delete_search_history( history_id: int = Path(..., ge=1), current_user: TokenData = Depends(get_current_user_token_data), db: AsyncSession = Depends(get_db) ): """删除某条搜索记录""" repo = SearchRepository(db) record = await repo.get_history_by_id(history_id) if not record: return JSONResponse({"success": False, "message": "记录不存在"}, status_code=404) if record["user_id"] != current_user.user_id: return JSONResponse({"success": False, "message": "无权操作"}, status_code=403) success = await repo.delete_history(history_id) if success: return JSONResponse({"success": True, "message": "已删除"}) return JSONResponse({"success": False, "message": "删除失败"}, status_code=500) @router.post("/history/clear") async def clear_search_history( current_user: TokenData = Depends(get_current_user_token_data), db: AsyncSession = Depends(get_db) ): """清空用户的搜索历史""" repo = SearchRepository(db) await repo.clear_user_history(current_user.user_id) return JSONResponse({"success": True, "message": "搜索历史已清空"}) ``` --- ### 2️⃣ 【热搜词】获取平台热搜榜 ```python @router.get("/hot-keywords") async def get_hot_keywords( hours: int = Query(24, ge=1, le=168), # 支持 1~7 天 limit: int = Query(10, ge=1, le=50), db: AsyncSession = Depends(get_db) ): """获取最近 N 小时内的热门搜索词""" repo = SearchRepository(db) start_time = datetime.now(timezone.utc) - timedelta(hours=hours) keywords = await repo.get_hot_keywords(start_time=start_time, limit=limit) return JSONResponse({ "success": True, "data": { "period_hours": hours, "total": len(keywords), "keywords": keywords } }) ``` --- ### 3️⃣ 【全局搜索】支持搜索分享、用户、聊天室等内容 ```python @router.get("") async def search_all( keyword: str = Query(..., min_length=1, max_length=50), type: str = Query("all", pattern="^(all|share|user)$"), page: int = Query(1, ge=1), size: int = Query(10, ge=1, le=50), current_user: TokenData = Depends(get_current_user_token_data), db: AsyncSession = Depends(get_db) ): """统一搜索接口:支持按类型搜索内容""" repo = SearchRepository(db) skip = (page - 1) * size # 记录搜索行为 await repo.add_search_record( keyword=keyword, user_id=current_user.user_id, search_time=datetime.now(timezone.utc) ) share_results = (0, []) user_results = (0, []) if type == "all" or type == "share": is_public = True # 所有人可见的分享 author_id = current_user.user_id # 自己的私有分享也可见 share_results = await repo.search_shares( keyword=keyword, is_public=is_public, author_id=author_id, skip=skip, limit=size ) if type == "all" or type == "user": is_admin = (current_user.role == "admin") user_results = await repo.search_users( keyword=keyword, current_user_id=current_user.user_id, is_admin=is_admin, skip=skip, limit=size ) return JSONResponse({ "success": True, "data": { "keyword": keyword, "type": type, "page": page, "size": size, "shares": { "total": share_results[0], "items": share_results[1] } if type in ["all", "share"] else None, "users": { "total": user_results[0], "items": user_results[1] } if type in ["all", "user"] else None } }) ``` --- ### 4️⃣ 【个性化推荐】基于用户兴趣推荐分享内容 ```python @router.get("/recommendations") async def get_recommendations( method: str = Query("auto", pattern="^(auto|keyword|dept|global)$"), keywords: Optional[str] = Query(None, description="多个关键词用逗号分隔"), current_user: TokenData = Depends(get_current_user_token_data), db: AsyncSession = Depends(get_db) ): """ 推荐分享内容: - auto: 自动选择策略(优先关键词 → 同部门 → 全局) - keyword: 基于关键词匹配推荐 - dept: 推荐同部门热门分享 - global: 推荐全站热门分享 """ repo = SearchRepository(db) limit = 5 exclude_user_id = current_user.user_id department_id = current_user.department_id shares = [] if method == "keyword" and keywords: kw_list = [k.strip() for k in keywords.split(",") if k.strip()] shares = await repo.recommend_shares_by_keywords( keywords=kw_list, limit=limit, exclude_user_id=exclude_user_id, department_id=department_id ) elif method == "dept": shares = await repo.get_dept_hot_shares( dept_id=department_id, limit=limit, exclude_user_id=exclude_user_id ) elif method == "global": shares = await repo.get_global_hot_shares( limit=limit, exclude_user_id=exclude_user_id ) else: # auto: 尝试多种策略 # 1. 尝试关键词推荐(从搜索历史提取高频词) history = await repo.get_user_history(user_id=exclude_user_id, days=7, limit=20) if history: top_words = [item["keyword"] for item in history[:5]] shares = await repo.recommend_shares_by_keywords( keywords=top_words, limit=limit, exclude_user_id=exclude_user_id, department_id=department_id ) if len(shares) >= 3: method = "keyword (auto)" # 2. 不够则 fallback 到部门推荐 if len(shares) < 3: shares = await repo.get_dept_hot_shares( dept_id=department_id, limit=limit, exclude_user_id=exclude_user_id ) method = "dept (auto)" # 3. 还不够?上全局热门 if len(shares) < 3: shares = await repo.get_global_hot_shares( limit=limit, exclude_user_id=exclude_user_id ) method = "global (auto)" # 去重 + 截取前5个 seen_ids = set() unique_shares = [] for s in shares: if s["id"] not in seen_ids: unique_shares.append(s) seen_ids.add(s["id"]) if len(unique_shares) >= limit: break return JSONResponse({ "success": True, "data": { "method_used": method, "recommended_count": len(unique_shares), "items": unique_shares } }) ``` --- ## ✅ 注册路由到主应用 ```python # main.py from api.search.router import router as search_router app.include_router(search_router) ``` --- ## ✅ 前端可实现的功能场景 | 功能 | 使用接口 | |------|---------| | 🔍 搜索框自动补全历史 | `GET /api/search/history` | | 🌟 显示“热搜榜”侧边栏 | `GET /api/search/hot-keywords` | | 🔄 删除某条搜索记录 | `DELETE /api/search/history/{id}` | | 🧹 清空搜索历史 | `POST /api/search/history/clear` | | 🎯 输入关键词触发全局搜索 | `GET /api/search?type=all&keyword=xxx` | | 👤 搜索特定用户 | `GET /api/search?type=user&keyword=张三` | | 📢 分享页底部“猜你喜欢” | `GET /api/search/recommendations?method=auto` | | 🏢 部门首页展示“本院热门分享” | `GET /api/search/recommendations?method=dept` | --- ## ✅ 最佳实践建议 1. **缓存优化**: - `hot-keywords` 可缓存 10 分钟(Redis) - `recommendations` 结果可按用户 ID 缓存 1 小时 2. **日志埋点**: ```python logger.info(f"🔍 User {uid} searched: {keyword}") ``` 3. **权限细化**: - 普通用户只能看到公开分享 + 自己的私有分享 - 管理员可搜索所有内容(未来可扩展) 4. **性能注意**: - 多表 JOIN 查询加索引: ```sql CREATE INDEX idx_share_title ON shares USING gin(to_tsvector('chinese', title)); CREATE INDEX idx_search_keyword ON search_records(keyword); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值